@eifi1/ui-kit 0.13.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/dist/components/amount-input.d.ts +6 -0
- package/dist/components/amount-input.js +35 -5
- package/dist/components/amount-input.js.map +1 -1
- package/dist/components/error-boundary.d.ts +8 -1
- package/dist/components/error-boundary.js +18 -2
- package/dist/components/error-boundary.js.map +1 -1
- package/dist/components/numpad-sheet.d.ts +7 -3
- package/dist/components/numpad-sheet.js +4 -3
- package/dist/components/numpad-sheet.js.map +1 -1
- package/dist/components/page-header.d.ts +55 -2
- package/dist/components/page-header.js +34 -3
- package/dist/components/page-header.js.map +1 -1
- package/dist/components/text.js.map +1 -1
- package/dist/components/tooltip.d.ts +31 -0
- package/dist/components/tooltip.js +33 -0
- package/dist/components/tooltip.js.map +1 -1
- package/dist/feedback/feedback-thread.d.ts +87 -6
- package/dist/feedback/feedback-thread.js +134 -58
- package/dist/feedback/feedback-thread.js.map +1 -1
- package/dist/feedback.d.ts +1 -1
- package/dist/i18n/locales/de.js +3 -1
- package/dist/i18n/locales/de.js.map +1 -1
- package/dist/i18n/locales/es.js +2 -1
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.js +2 -1
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hu.js +2 -1
- package/dist/i18n/locales/hu.js.map +1 -1
- package/dist/i18n/locales/it.js +2 -1
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/zh.js +2 -1
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/lib/format.js +1 -1
- package/dist/lib/format.js.map +1 -1
- package/dist/rhf/fields.d.ts +3 -1
- package/dist/rhf/fields.js.map +1 -1
- package/package.json +1 -1
- package/src/components/amount-input.tsx +73 -7
- package/src/components/error-boundary.tsx +33 -3
- package/src/components/numpad-sheet.tsx +13 -4
- package/src/components/page-header.tsx +98 -3
- package/src/components/text.tsx +2 -1
- package/src/components/tooltip.tsx +109 -2
- package/src/feedback/feedback-thread.tsx +229 -37
- package/src/i18n/locales/de.ts +2 -0
- package/src/i18n/locales/es.ts +1 -0
- package/src/i18n/locales/fr.ts +1 -0
- package/src/i18n/locales/hu.ts +1 -0
- package/src/i18n/locales/it.ts +1 -0
- package/src/i18n/locales/zh.ts +1 -0
- package/src/lib/format.ts +3 -1
- package/src/rhf/fields.tsx +3 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/i18n/locales/zh.ts"],"sourcesContent":["import { formatFileSize } from \"../kit-labels\";\nimport type { UiKitLabels } from \"../kit-labels\";\n\n/**\n * The kit's words in Chinese (Simplified): every namespace of {@link UiKitLabels}, for\n * `<UiKitProvider labels={UI_KIT_LABELS_ZH}>`.\n *\n * Self-contained on purpose — nothing but the kit's own `formatFileSize` — so it works\n * as a starting point to copy and adjust. Counts and sizes are formatted with\n * `zh-CN` digits; {@link uiKitLabelsZh} takes another number locale\n * (e.g. `\"de-CH\"` for 1’234) without touching the words.\n */\nexport function uiKitLabelsZh(numberLocale = \"zh-CN\"): UiKitLabels {\n const num = new Intl.NumberFormat(numberLocale);\n const n = (value: number) => num.format(value);\n\n return {\n feedbackAttachment: {\n attachmentAdd: \"附加图片\",\n attachmentCapture: \"截取屏幕\",\n attachmentPaste: \"……或从剪贴板粘贴截图。\",\n attachmentRemove: \"移除附件\",\n },\n feedbackDialog: {\n title: \"发送反馈\",\n category: \"类别\",\n subject: \"主题\",\n body: \"发生了什么?\",\n attachment: \"截图\",\n submitHint: \"Ctrl/⌘ + Enter 发送\",\n cancel: \"取消\",\n save: \"发送\",\n },\n feedbackThread: {\n thread: \"评论\",\n empty: \"暂无评论\",\n loading: \"正在加载评论…\",\n you: \"我\",\n staff: \"工作人员\",\n attachments: \"附件\",\n },\n feedbackComposer: {\n field: \"撰写评论\",\n placeholder: \"撰写评论…\",\n send: \"发送\",\n sendHint: (modifier) => `${modifier} + Enter 发送`,\n },\n accountSettings: {\n profile: {\n title: \"个人资料\",\n email: \"电子邮箱\",\n role: \"角色\",\n memberSince: \"注册时间\",\n displayName: \"显示名称\",\n save: \"保存\",\n },\n password: {\n title: \"修改密码\",\n current: \"当前密码\",\n next: \"新密码\",\n confirm: \"确认新密码\",\n submit: \"修改密码\",\n tooShort: \"新密码太短。\",\n mismatch: \"两次输入的密码不一致。\",\n },\n twoFactor: {\n status: \"双重验证\",\n enabledText: \"已开启\",\n disabledText: \"未开启\",\n enable: \"设置双重验证\",\n scanHint: \"请用身份验证器应用扫描此二维码,然后输入应用显示的验证码。\",\n codeLabel: \"验证码\",\n verify: \"验证并开启\",\n disableSection: \"关闭双重验证\",\n password: \"当前密码\",\n disable: \"关闭\",\n qrAlt: \"身份验证器应用的二维码\",\n secretHint: \"无法扫描?请改为在应用中输入此密钥:\",\n copySecret: \"复制密钥\",\n },\n passkeys: {\n title: \"通行密钥\",\n description: \"使用指纹、面容或设备 PIN 登录,无需密码。\",\n empty: \"暂无通行密钥\",\n loading: \"正在加载通行密钥…\",\n list: \"已注册的通行密钥\",\n nameLabel: \"名称(可选)\",\n namePlaceholder: \"例如:笔记本电脑、手机\",\n add: \"添加通行密钥\",\n adding: \"正在等待设备…\",\n rename: \"重命名\",\n renameItem: (name) => `重命名 ${name}`,\n renameField: (name) => `${name} 的新名称`,\n save: \"保存\",\n cancel: \"取消\",\n delete: \"删除\",\n deleteItem: (name) => `删除 ${name}`,\n deleteConfirm: (name) => `删除“${name}”?删除后将无法再用它登录。`,\n confirmDelete: \"删除通行密钥\",\n created: (date) => `添加于 ${date}`,\n lastUsed: (date) => `上次使用:${date}`,\n neverUsed: \"从未使用\",\n },\n },\n measuredGrid: {\n view: \"表格视图\",\n cellsView: \"单元格\",\n textView: \"文本\",\n addRow: \"添加行\",\n removeRow: (row) => `删除第 ${row} 行`,\n clear: \"清空表格\",\n pasteHint: \"可将电子表格中的一块数据粘贴到任意单元格\",\n cell: (column, row) => `${column},第 ${row} 行`,\n rowNumber: \"行\",\n rowActions: \"行操作\",\n keyboardHint:\n \"方向键在单元格之间移动。直接输入替换单元格内容,F2 编辑,Esc 撤销编辑。回车向下移动,并在末尾添加一行。\",\n lineError: (line) => `无法读取第 ${line} 行`,\n points: (count) => `${count} 个点`,\n problems: (count) => `${count} 个单元格不是数字`,\n },\n pageContents: { title: \"本页目录\" },\n common: {\n dismiss: \"关闭\",\n close: \"关闭\",\n clear: \"清除\",\n search: \"搜索\",\n done: \"完成\",\n cancel: \"取消\",\n save: \"保存\",\n back: \"上一步\",\n next: \"下一步\",\n remove: \"移除\",\n loading: \"加载中…\",\n noResults: \"无结果\",\n // Full-width colon, no space after it.\n fieldValue: (field, value) => `${field}:${value}`,\n opensInNewTab: \"在新标签页中打开\",\n },\n dataTable: {\n columns: \"列\",\n selectAllRows: \"全选所有行\",\n sortHint: \"点击排序 · 按住 Shift 点击可添加排序\",\n filter: \"筛选\",\n close: \"关闭\",\n selectRow: \"选择行\",\n autoSize: \"自动调整列宽\",\n loading: \"加载中…\",\n filters: \"筛选条件\",\n clearAll: \"全部清除\",\n done: \"完成\",\n pageSize: \"每页行数\",\n pageSizeAll: \"全部\",\n prevPage: \"上一页\",\n nextPage: \"下一页\",\n clearFilter: \"清除筛选\",\n filterPlaceholder: \"筛选…\",\n selectFilter: \"选择\",\n selectAll: \"全部\",\n selectNone: \"无\",\n dateFrom: \"从\",\n dateTo: \"至\",\n numberMin: \"最小值\",\n numberMax: \"最大值\",\n numberAbs: \"绝对值\",\n presets: {\n today: \"今天\",\n yesterday: \"昨天\",\n this_week: \"本周\",\n last_week: \"上周\",\n last_7_days: \"最近 7 天\",\n last_30_days: \"最近 30 天\",\n this_month: \"本月\",\n last_month: \"上月\",\n last_3_months: \"最近 3 个月\",\n ytd: \"今年至今\",\n last_year: \"去年\",\n },\n table: \"数据表格\",\n filterResults: (shown, total) => `显示 ${n(shown)} 行,共 ${n(total)} 行`,\n sortedAscending: (column) => `已按“${column}”升序排序`,\n sortedDescending: (column) => `已按“${column}”降序排序`,\n sortCleared: (column) => `已取消“${column}”的排序`,\n pageChanged: (page, totalPages) => `第 ${n(page)} 页,共 ${n(totalPages)} 页`,\n pageRange: (from, to, total) => `${n(from)}–${n(to)} / ${n(total)}`,\n rowCount: (total) => n(total),\n columnsCount: (visible, total) => `列(${n(visible)}/${n(total)})`,\n empty: \"暂无条目\",\n actions: \"操作\",\n edit: \"编辑\",\n delete: \"删除\",\n booleanTrue: \"是\",\n booleanFalse: \"否\",\n booleanUnset: \"未设置\",\n },\n miniCalendar: {\n previousMonth: \"上个月\",\n nextMonth: \"下个月\",\n // Already formatted in the provider's locale (\"2026年9月14日星期一\").\n day: (date) => date,\n chooseStart: \"请选择开始日期\",\n chooseEnd: \"请选择结束日期\",\n startSelected: (date) => `已选择 ${date} 为开始日期。请选择结束日期。`,\n rangeSelected: (from, to) => `已选择 ${from} 至 ${to}。如需重新选择,请先选择开始日期。`,\n },\n monthPicker: {\n previousYear: \"上一年\",\n nextYear: \"下一年\",\n panel: \"选择月份\",\n month: (monthYear) => monthYear,\n previousMonth: \"上个月\",\n nextMonth: \"下个月\",\n today: \"今天\",\n },\n calendarHeatmap: {\n grid: \"每日数值\",\n day: (date, value) => `${date}:${value}`,\n less: \"较少\",\n more: \"较多\",\n truncated: (count) =>\n `仅显示最近的日期;另有 ${n(count)} 天未显示。`,\n },\n datePicker: {\n apply: \"应用\",\n cancel: \"取消\",\n presets: \"快捷范围\",\n panel: \"选择日期\",\n rangePanel: \"选择日期范围\",\n clear: \"清除\",\n previousDay: \"前一天\",\n nextDay: \"后一天\",\n today: \"今天\",\n },\n popover: {\n panel: \"弹出框\",\n },\n combobox: {\n search: \"搜索\",\n noResults: \"无结果\",\n clear: \"清除\",\n loading: \"加载中…\",\n create: (query) => `创建“${query}”`,\n selectedCount: (count) => `已选 ${n(count)} 项`,\n loadError: \"无法加载结果\",\n resultCount: (count) => `${n(count)} 个结果`,\n minChars: (count) => `请至少输入 ${n(count)} 个字符`,\n },\n multiSelect: {\n search: \"搜索\",\n selectAll: \"全选\",\n clear: \"清除\",\n all: \"全部\",\n // The bare count, as in English: the trigger has always shown just the number.\n selectedCount: (count) => n(count),\n },\n calculator: {\n open: \"打开计算器\",\n panel: \"计算器\",\n calculation: \"算式\",\n backspace: \"退格\",\n clear: \"清除\",\n equals: \"等于\",\n done: \"完成\",\n plus: \"加\",\n minus: \"减\",\n times: \"乘\",\n divide: \"除以\",\n decimal: \"小数点\",\n },\n currency: {\n currency: \"货币\",\n search: \"搜索货币\",\n },\n chipInput: {\n added: (value) => `已添加“${value}”`,\n removed: (value) => `已移除“${value}”`,\n remove: \"移除\",\n atLimit: (max) => `已达上限(${n(max)} 项)`,\n duplicate: (value) => `“${value}”已在列表中`,\n },\n swatchPicker: {\n none: \"无颜色\",\n mixed: \"混合:所选项目的颜色各不相同\",\n },\n iconPicker: {\n none: \"无图标\",\n mixed: \"混合:所选项目的图标各不相同\",\n search: \"搜索图标\",\n noResults: \"没有匹配的图标\",\n resultCount: (count) => `${n(count)} 个图标`,\n },\n fieldSync: {\n synced: \"已保存\",\n edited: \"有未保存的更改\",\n pending: \"正在保存…\",\n error: \"保存失败\",\n retry: \"重试\",\n },\n passwordReveal: {\n show: \"显示密码\",\n hide: \"隐藏密码\",\n },\n dangerConfirm: {\n arm: \"删除…\",\n confirm: \"删除\",\n cancel: \"取消\",\n prompt: \"此操作无法撤销。\",\n password: \"密码\",\n phrase: (phrase) => `输入“${phrase}”以确认`,\n },\n tabs: {\n add: \"添加标签页\",\n // Quoted, so the spacing rule holds whether the tab's name is Han or Latin.\n remove: (tab) => `移除“${tab}”`,\n },\n appShell: {\n collapse: \"收起侧边栏\",\n expand: \"展开侧边栏\",\n toggleGroup: (groupLabel) => `${groupLabel}:页面`,\n },\n topBar: {\n theme: \"切换主题\",\n palette: \"外观预设\",\n language: \"语言\",\n switchRole: \"切换角色\",\n role: (value) => `角色:${value}`,\n },\n pickerSheet: {\n close: \"关闭\",\n },\n dialogFrame: {\n close: \"关闭\",\n },\n bulkActionBar: {\n selected: (count) => `已选择 ${n(count)} 项`,\n clear: \"清除选择\",\n cleared: \"已清除选择\",\n },\n swipeableRow: {\n actions: \"行操作\",\n },\n file: {\n // The kit's own `Intl` unit formatting, pinned to this locale.\n size: (bytes) => formatFileSize(bytes, numberLocale),\n },\n filePicker: {\n dropzone: \"文件上传\",\n browse: \"浏览\",\n empty: \"将文件拖放到此处\",\n emptyMultiple: \"将文件拖放到此处\",\n hint: (accept) => (accept ? `支持:${accept}` : \"任意文件类型\"),\n busy: \"正在上传…\",\n rejectedPick: (count) => (count === 1 ? \"未添加该文件\" : `${count} 个文件均未添加`),\n rejectedType: (name) => `“${name}”的文件类型不受支持`,\n rejectedTypeOnly: (accept) => `仅限 ${accept} 文件`,\n rejectedSize: (name, maxSize) => `“${name}”超过 ${maxSize}`,\n rejectedCount: (name, maxFiles) => `未添加“${name}”:最多 ${n(maxFiles)} 个文件`,\n rejectedInvalid: (name) => `“${name}”无法在此使用`,\n rejectedMany: (count) => `${n(count)} 个文件未添加`,\n selected: (count, firstName) =>\n count === 1 ? `已选择“${firstName}”` : `已选择 ${n(count)} 个文件`,\n remove: (name) => `移除“${name}”`,\n clearAll: \"移除所有文件\",\n removed: (name) => `已移除“${name}”`,\n cleared: \"已移除所有文件\",\n },\n wizard: {\n done: \"完成\",\n cancel: \"取消\",\n back: \"上一步\",\n next: \"下一步\",\n skip: \"跳过\",\n finish: \"完成\",\n submitting: \"正在创建…\",\n steps: \"步骤\",\n step: (current, total) => `第 ${n(current)} 步,共 ${n(total)} 步`,\n cancelTitle: \"放弃此表单?\",\n confirmCancel: \"已填写的内容将会丢失。\",\n cancelConfirmLabel: \"放弃\",\n cancelDismissLabel: \"继续编辑\",\n reviewTitle: \"确认信息\",\n edit: \"编辑\",\n missingRequired: \"请填写所有必填字段。\",\n genericError: \"发生错误\",\n },\n tour: {\n next: \"下一步\",\n back: \"上一步\",\n skip: \"跳过\",\n done: \"完成\",\n awaitClickHint: \"点击高亮的元素以继续\",\n step: (current, total) => `${n(current)} / ${n(total)}`,\n },\n commandPalette: {\n clear: \"清除搜索\",\n submit: \"搜索\",\n close: \"关闭\",\n placeholder: \"搜索…\",\n empty: \"无结果\",\n loading: \"搜索中…\",\n dialog: \"搜索\",\n error: \"搜索失败,请重试。\",\n },\n globalSearch: {\n trigger: \"搜索\",\n placeholder: \"搜索或跳转到…\",\n shortcut: (keys) => `搜索(${keys})`,\n suggestions: \"试试\",\n results: \"结果\",\n },\n sparkline: {\n rising: (first, last) => `从 ${first} 上升到 ${last}`,\n falling: (first, last) => `从 ${first} 下降到 ${last}`,\n flat: (value) => `保持在 ${value} 不变`,\n single: (value) => `仅一个值:${value}`,\n noData: \"无数据\",\n named: (name, summary) => `${name}:${summary}`,\n },\n statTile: {\n increase: (amount) => `上升 ${amount}`,\n decrease: (amount) => `下降 ${amount}`,\n unchanged: \"无变化\",\n better: (change) => `${change}(向好)`,\n worse: (change) => `${change}(变差)`,\n noValue: \"无数据\",\n loading: \"加载中…\",\n },\n signaturePad: {\n label: \"签名\",\n instructions: \"请使用鼠标、手指或触控笔在框内签名。\",\n typedFallbackHint: \"如果无法手写,可以改为输入姓名。\",\n empty: \"尚未签名\",\n signed: \"已签名\",\n undo: \"撤销上一笔\",\n clear: \"清除\",\n save: \"保存签名\",\n useTyped: \"改为输入姓名\",\n useDrawn: \"改为手写\",\n typedName: \"姓名\",\n cleared: \"签名已清除\",\n undone: \"已撤销上一笔\",\n viewEmpty: \"未签名\",\n viewDrawn: \"手写签名\",\n // Quoted, so the spacing rule holds whether the name is Han or Latin.\n viewTyped: (name) => `以输入的姓名“${name}”签名`,\n },\n passwordStrength: {\n tooShort: \"太短\",\n weak: \"弱\",\n fair: \"一般\",\n good: \"良好\",\n strong: \"强\",\n announcement: (level) => `密码强度:${level}`,\n // Unformatted, as in the English default.\n ruleLength: (minLength) => `至少 ${minLength} 个字符`,\n ruleCase: \"包含大写和小写字母\",\n ruleDigit: \"包含数字\",\n ruleSymbol: \"包含符号\",\n optional: (rule) => `${rule}(可选)`,\n met: \"已满足:\",\n notMet: \"未满足:\",\n tooLong: (maxBytes) => `最多 ${maxBytes} 个字符(带重音的字母和表情符号按多个字符计算)。`,\n },\n seriesChart: {\n resetZoom: \"重置缩放\",\n zoomHint:\n \"拖动以缩放:近似正方形的选区同时缩放两条坐标轴,细长的选区只缩放其所沿的那条轴。双击可重置。\",\n empty: \"无数据\",\n legend: \"数据系列\",\n points: \"图表数值\",\n },\n pieChart: {\n slices: \"图表扇区\",\n slice: (label, value, percent) => `${label}:${value}(${percent})`,\n total: \"合计\",\n empty: \"无数据\",\n legend: \"类别\",\n },\n confirmDialog: {\n confirm: \"确认\",\n cancel: \"取消\",\n },\n floatingPanel: {\n close: \"关闭\",\n badge: (count) => `${n(count)} 条新内容`,\n },\n copyButton: {\n copy: \"复制\",\n copied: \"已复制\",\n failed: \"复制失败\",\n copiedAnnouncement: \"已复制到剪贴板\",\n failedAnnouncement: \"无法复制到剪贴板\",\n },\n list: {\n unread: \"未读\",\n opensInNewTab: \"在新标签页中打开\",\n },\n breadcrumbs: {\n label: \"面包屑导航\",\n showAll: \"显示完整路径\",\n },\n toast: {\n close: \"关闭通知\",\n notifications: \"通知\",\n undo: \"撤销\",\n redo: \"重做\",\n },\n form: {\n save: \"保存\",\n cancel: \"取消\",\n },\n descriptionList: {\n empty: \"—\",\n },\n lineItems: {\n add: \"添加行\",\n remove: (row) => `删除第 ${row} 行`,\n confirmRemove: (row) => `删除第 ${row} 行?再次按下以确认`,\n row: (row) => `第 ${row} 行`,\n cell: (column, row) => `${column},第 ${row} 行`,\n totals: \"合计\",\n },\n progressBar: {\n unlimited: \"无限制\",\n overLimit: (amount) => `超出限额 ${amount}`,\n },\n signedAmount: {\n positive: (amount) => `正 ${amount}`,\n negative: (amount) => `负 ${amount}`,\n },\n errorBoundary: {\n title: \"出错了\",\n message: \"无法显示页面的这一部分。请重试或重新加载页面。\",\n retry: \"重试\",\n details: \"错误详情\",\n reload: \"重新加载\",\n updateTitle: \"有新版本可用\",\n updateMessage: \"自此页面加载以来,应用的部分内容已更新。请重新加载以获取新版本。\",\n offlineTitle: \"当前处于离线状态\",\n offlineMessage: \"没有网络连接,无法加载此页面。请恢复连接后重新加载页面。\",\n copyReport: \"复制错误报告\",\n reported: \"此错误已自动报告。\",\n reportedAs: (reference) => `报告编号:${reference}`,\n },\n authedImage: {\n loading: \"正在加载图片…\",\n loadError: \"无法加载图片\",\n failedImage: (alt) => `${alt}:无法加载图片`,\n },\n imageGrid: {\n list: \"图片\",\n item: (index, count) => `第 ${n(index)} 张,共 ${n(count)} 张`,\n actions: (name) => `${name}的操作`,\n },\n lightbox: {\n dialog: \"图片查看器\",\n close: \"关闭\",\n previous: \"上一张\",\n next: \"下一张\",\n counter: (index, count) => `${n(index)} / ${n(count)}`,\n position: (index, count) => `第 ${n(index)} 张,共 ${n(count)} 张`,\n download: \"下载\",\n zoom: \"缩放\",\n noPreview: \"此文件无法预览\",\n openInNewTab: \"在新标签页中打开\",\n },\n };\n}\n\nexport const UI_KIT_LABELS_ZH: UiKitLabels = uiKitLabelsZh();\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/i18n/locales/zh.ts"],"sourcesContent":["import { formatFileSize } from \"../kit-labels\";\nimport type { UiKitLabels } from \"../kit-labels\";\n\n/**\n * The kit's words in Chinese (Simplified): every namespace of {@link UiKitLabels}, for\n * `<UiKitProvider labels={UI_KIT_LABELS_ZH}>`.\n *\n * Self-contained on purpose — nothing but the kit's own `formatFileSize` — so it works\n * as a starting point to copy and adjust. Counts and sizes are formatted with\n * `zh-CN` digits; {@link uiKitLabelsZh} takes another number locale\n * (e.g. `\"de-CH\"` for 1’234) without touching the words.\n */\nexport function uiKitLabelsZh(numberLocale = \"zh-CN\"): UiKitLabels {\n const num = new Intl.NumberFormat(numberLocale);\n const n = (value: number) => num.format(value);\n\n return {\n feedbackAttachment: {\n attachmentAdd: \"附加图片\",\n attachmentCapture: \"截取屏幕\",\n attachmentPaste: \"……或从剪贴板粘贴截图。\",\n attachmentRemove: \"移除附件\",\n },\n feedbackDialog: {\n title: \"发送反馈\",\n category: \"类别\",\n subject: \"主题\",\n body: \"发生了什么?\",\n attachment: \"截图\",\n submitHint: \"Ctrl/⌘ + Enter 发送\",\n cancel: \"取消\",\n save: \"发送\",\n },\n feedbackThread: {\n thread: \"评论\",\n empty: \"暂无评论\",\n loading: \"正在加载评论…\",\n you: \"我\",\n staff: \"工作人员\",\n attachments: \"附件\",\n },\n feedbackComposer: {\n field: \"撰写评论\",\n placeholder: \"撰写评论…\",\n send: \"发送\",\n sendHint: (modifier) => `${modifier} + Enter 发送`,\n sendHintEnter: \"Enter 发送,Shift + Enter 换行\",\n },\n accountSettings: {\n profile: {\n title: \"个人资料\",\n email: \"电子邮箱\",\n role: \"角色\",\n memberSince: \"注册时间\",\n displayName: \"显示名称\",\n save: \"保存\",\n },\n password: {\n title: \"修改密码\",\n current: \"当前密码\",\n next: \"新密码\",\n confirm: \"确认新密码\",\n submit: \"修改密码\",\n tooShort: \"新密码太短。\",\n mismatch: \"两次输入的密码不一致。\",\n },\n twoFactor: {\n status: \"双重验证\",\n enabledText: \"已开启\",\n disabledText: \"未开启\",\n enable: \"设置双重验证\",\n scanHint: \"请用身份验证器应用扫描此二维码,然后输入应用显示的验证码。\",\n codeLabel: \"验证码\",\n verify: \"验证并开启\",\n disableSection: \"关闭双重验证\",\n password: \"当前密码\",\n disable: \"关闭\",\n qrAlt: \"身份验证器应用的二维码\",\n secretHint: \"无法扫描?请改为在应用中输入此密钥:\",\n copySecret: \"复制密钥\",\n },\n passkeys: {\n title: \"通行密钥\",\n description: \"使用指纹、面容或设备 PIN 登录,无需密码。\",\n empty: \"暂无通行密钥\",\n loading: \"正在加载通行密钥…\",\n list: \"已注册的通行密钥\",\n nameLabel: \"名称(可选)\",\n namePlaceholder: \"例如:笔记本电脑、手机\",\n add: \"添加通行密钥\",\n adding: \"正在等待设备…\",\n rename: \"重命名\",\n renameItem: (name) => `重命名 ${name}`,\n renameField: (name) => `${name} 的新名称`,\n save: \"保存\",\n cancel: \"取消\",\n delete: \"删除\",\n deleteItem: (name) => `删除 ${name}`,\n deleteConfirm: (name) => `删除“${name}”?删除后将无法再用它登录。`,\n confirmDelete: \"删除通行密钥\",\n created: (date) => `添加于 ${date}`,\n lastUsed: (date) => `上次使用:${date}`,\n neverUsed: \"从未使用\",\n },\n },\n measuredGrid: {\n view: \"表格视图\",\n cellsView: \"单元格\",\n textView: \"文本\",\n addRow: \"添加行\",\n removeRow: (row) => `删除第 ${row} 行`,\n clear: \"清空表格\",\n pasteHint: \"可将电子表格中的一块数据粘贴到任意单元格\",\n cell: (column, row) => `${column},第 ${row} 行`,\n rowNumber: \"行\",\n rowActions: \"行操作\",\n keyboardHint:\n \"方向键在单元格之间移动。直接输入替换单元格内容,F2 编辑,Esc 撤销编辑。回车向下移动,并在末尾添加一行。\",\n lineError: (line) => `无法读取第 ${line} 行`,\n points: (count) => `${count} 个点`,\n problems: (count) => `${count} 个单元格不是数字`,\n },\n pageContents: { title: \"本页目录\" },\n common: {\n dismiss: \"关闭\",\n close: \"关闭\",\n clear: \"清除\",\n search: \"搜索\",\n done: \"完成\",\n cancel: \"取消\",\n save: \"保存\",\n back: \"上一步\",\n next: \"下一步\",\n remove: \"移除\",\n loading: \"加载中…\",\n noResults: \"无结果\",\n // Full-width colon, no space after it.\n fieldValue: (field, value) => `${field}:${value}`,\n opensInNewTab: \"在新标签页中打开\",\n },\n dataTable: {\n columns: \"列\",\n selectAllRows: \"全选所有行\",\n sortHint: \"点击排序 · 按住 Shift 点击可添加排序\",\n filter: \"筛选\",\n close: \"关闭\",\n selectRow: \"选择行\",\n autoSize: \"自动调整列宽\",\n loading: \"加载中…\",\n filters: \"筛选条件\",\n clearAll: \"全部清除\",\n done: \"完成\",\n pageSize: \"每页行数\",\n pageSizeAll: \"全部\",\n prevPage: \"上一页\",\n nextPage: \"下一页\",\n clearFilter: \"清除筛选\",\n filterPlaceholder: \"筛选…\",\n selectFilter: \"选择\",\n selectAll: \"全部\",\n selectNone: \"无\",\n dateFrom: \"从\",\n dateTo: \"至\",\n numberMin: \"最小值\",\n numberMax: \"最大值\",\n numberAbs: \"绝对值\",\n presets: {\n today: \"今天\",\n yesterday: \"昨天\",\n this_week: \"本周\",\n last_week: \"上周\",\n last_7_days: \"最近 7 天\",\n last_30_days: \"最近 30 天\",\n this_month: \"本月\",\n last_month: \"上月\",\n last_3_months: \"最近 3 个月\",\n ytd: \"今年至今\",\n last_year: \"去年\",\n },\n table: \"数据表格\",\n filterResults: (shown, total) => `显示 ${n(shown)} 行,共 ${n(total)} 行`,\n sortedAscending: (column) => `已按“${column}”升序排序`,\n sortedDescending: (column) => `已按“${column}”降序排序`,\n sortCleared: (column) => `已取消“${column}”的排序`,\n pageChanged: (page, totalPages) => `第 ${n(page)} 页,共 ${n(totalPages)} 页`,\n pageRange: (from, to, total) => `${n(from)}–${n(to)} / ${n(total)}`,\n rowCount: (total) => n(total),\n columnsCount: (visible, total) => `列(${n(visible)}/${n(total)})`,\n empty: \"暂无条目\",\n actions: \"操作\",\n edit: \"编辑\",\n delete: \"删除\",\n booleanTrue: \"是\",\n booleanFalse: \"否\",\n booleanUnset: \"未设置\",\n },\n miniCalendar: {\n previousMonth: \"上个月\",\n nextMonth: \"下个月\",\n // Already formatted in the provider's locale (\"2026年9月14日星期一\").\n day: (date) => date,\n chooseStart: \"请选择开始日期\",\n chooseEnd: \"请选择结束日期\",\n startSelected: (date) => `已选择 ${date} 为开始日期。请选择结束日期。`,\n rangeSelected: (from, to) => `已选择 ${from} 至 ${to}。如需重新选择,请先选择开始日期。`,\n },\n monthPicker: {\n previousYear: \"上一年\",\n nextYear: \"下一年\",\n panel: \"选择月份\",\n month: (monthYear) => monthYear,\n previousMonth: \"上个月\",\n nextMonth: \"下个月\",\n today: \"今天\",\n },\n calendarHeatmap: {\n grid: \"每日数值\",\n day: (date, value) => `${date}:${value}`,\n less: \"较少\",\n more: \"较多\",\n truncated: (count) =>\n `仅显示最近的日期;另有 ${n(count)} 天未显示。`,\n },\n datePicker: {\n apply: \"应用\",\n cancel: \"取消\",\n presets: \"快捷范围\",\n panel: \"选择日期\",\n rangePanel: \"选择日期范围\",\n clear: \"清除\",\n previousDay: \"前一天\",\n nextDay: \"后一天\",\n today: \"今天\",\n },\n popover: {\n panel: \"弹出框\",\n },\n combobox: {\n search: \"搜索\",\n noResults: \"无结果\",\n clear: \"清除\",\n loading: \"加载中…\",\n create: (query) => `创建“${query}”`,\n selectedCount: (count) => `已选 ${n(count)} 项`,\n loadError: \"无法加载结果\",\n resultCount: (count) => `${n(count)} 个结果`,\n minChars: (count) => `请至少输入 ${n(count)} 个字符`,\n },\n multiSelect: {\n search: \"搜索\",\n selectAll: \"全选\",\n clear: \"清除\",\n all: \"全部\",\n // The bare count, as in English: the trigger has always shown just the number.\n selectedCount: (count) => n(count),\n },\n calculator: {\n open: \"打开计算器\",\n panel: \"计算器\",\n calculation: \"算式\",\n backspace: \"退格\",\n clear: \"清除\",\n equals: \"等于\",\n done: \"完成\",\n plus: \"加\",\n minus: \"减\",\n times: \"乘\",\n divide: \"除以\",\n decimal: \"小数点\",\n },\n currency: {\n currency: \"货币\",\n search: \"搜索货币\",\n },\n chipInput: {\n added: (value) => `已添加“${value}”`,\n removed: (value) => `已移除“${value}”`,\n remove: \"移除\",\n atLimit: (max) => `已达上限(${n(max)} 项)`,\n duplicate: (value) => `“${value}”已在列表中`,\n },\n swatchPicker: {\n none: \"无颜色\",\n mixed: \"混合:所选项目的颜色各不相同\",\n },\n iconPicker: {\n none: \"无图标\",\n mixed: \"混合:所选项目的图标各不相同\",\n search: \"搜索图标\",\n noResults: \"没有匹配的图标\",\n resultCount: (count) => `${n(count)} 个图标`,\n },\n fieldSync: {\n synced: \"已保存\",\n edited: \"有未保存的更改\",\n pending: \"正在保存…\",\n error: \"保存失败\",\n retry: \"重试\",\n },\n passwordReveal: {\n show: \"显示密码\",\n hide: \"隐藏密码\",\n },\n dangerConfirm: {\n arm: \"删除…\",\n confirm: \"删除\",\n cancel: \"取消\",\n prompt: \"此操作无法撤销。\",\n password: \"密码\",\n phrase: (phrase) => `输入“${phrase}”以确认`,\n },\n tabs: {\n add: \"添加标签页\",\n // Quoted, so the spacing rule holds whether the tab's name is Han or Latin.\n remove: (tab) => `移除“${tab}”`,\n },\n appShell: {\n collapse: \"收起侧边栏\",\n expand: \"展开侧边栏\",\n toggleGroup: (groupLabel) => `${groupLabel}:页面`,\n },\n topBar: {\n theme: \"切换主题\",\n palette: \"外观预设\",\n language: \"语言\",\n switchRole: \"切换角色\",\n role: (value) => `角色:${value}`,\n },\n pickerSheet: {\n close: \"关闭\",\n },\n dialogFrame: {\n close: \"关闭\",\n },\n bulkActionBar: {\n selected: (count) => `已选择 ${n(count)} 项`,\n clear: \"清除选择\",\n cleared: \"已清除选择\",\n },\n swipeableRow: {\n actions: \"行操作\",\n },\n file: {\n // The kit's own `Intl` unit formatting, pinned to this locale.\n size: (bytes) => formatFileSize(bytes, numberLocale),\n },\n filePicker: {\n dropzone: \"文件上传\",\n browse: \"浏览\",\n empty: \"将文件拖放到此处\",\n emptyMultiple: \"将文件拖放到此处\",\n hint: (accept) => (accept ? `支持:${accept}` : \"任意文件类型\"),\n busy: \"正在上传…\",\n rejectedPick: (count) => (count === 1 ? \"未添加该文件\" : `${count} 个文件均未添加`),\n rejectedType: (name) => `“${name}”的文件类型不受支持`,\n rejectedTypeOnly: (accept) => `仅限 ${accept} 文件`,\n rejectedSize: (name, maxSize) => `“${name}”超过 ${maxSize}`,\n rejectedCount: (name, maxFiles) => `未添加“${name}”:最多 ${n(maxFiles)} 个文件`,\n rejectedInvalid: (name) => `“${name}”无法在此使用`,\n rejectedMany: (count) => `${n(count)} 个文件未添加`,\n selected: (count, firstName) =>\n count === 1 ? `已选择“${firstName}”` : `已选择 ${n(count)} 个文件`,\n remove: (name) => `移除“${name}”`,\n clearAll: \"移除所有文件\",\n removed: (name) => `已移除“${name}”`,\n cleared: \"已移除所有文件\",\n },\n wizard: {\n done: \"完成\",\n cancel: \"取消\",\n back: \"上一步\",\n next: \"下一步\",\n skip: \"跳过\",\n finish: \"完成\",\n submitting: \"正在创建…\",\n steps: \"步骤\",\n step: (current, total) => `第 ${n(current)} 步,共 ${n(total)} 步`,\n cancelTitle: \"放弃此表单?\",\n confirmCancel: \"已填写的内容将会丢失。\",\n cancelConfirmLabel: \"放弃\",\n cancelDismissLabel: \"继续编辑\",\n reviewTitle: \"确认信息\",\n edit: \"编辑\",\n missingRequired: \"请填写所有必填字段。\",\n genericError: \"发生错误\",\n },\n tour: {\n next: \"下一步\",\n back: \"上一步\",\n skip: \"跳过\",\n done: \"完成\",\n awaitClickHint: \"点击高亮的元素以继续\",\n step: (current, total) => `${n(current)} / ${n(total)}`,\n },\n commandPalette: {\n clear: \"清除搜索\",\n submit: \"搜索\",\n close: \"关闭\",\n placeholder: \"搜索…\",\n empty: \"无结果\",\n loading: \"搜索中…\",\n dialog: \"搜索\",\n error: \"搜索失败,请重试。\",\n },\n globalSearch: {\n trigger: \"搜索\",\n placeholder: \"搜索或跳转到…\",\n shortcut: (keys) => `搜索(${keys})`,\n suggestions: \"试试\",\n results: \"结果\",\n },\n sparkline: {\n rising: (first, last) => `从 ${first} 上升到 ${last}`,\n falling: (first, last) => `从 ${first} 下降到 ${last}`,\n flat: (value) => `保持在 ${value} 不变`,\n single: (value) => `仅一个值:${value}`,\n noData: \"无数据\",\n named: (name, summary) => `${name}:${summary}`,\n },\n statTile: {\n increase: (amount) => `上升 ${amount}`,\n decrease: (amount) => `下降 ${amount}`,\n unchanged: \"无变化\",\n better: (change) => `${change}(向好)`,\n worse: (change) => `${change}(变差)`,\n noValue: \"无数据\",\n loading: \"加载中…\",\n },\n signaturePad: {\n label: \"签名\",\n instructions: \"请使用鼠标、手指或触控笔在框内签名。\",\n typedFallbackHint: \"如果无法手写,可以改为输入姓名。\",\n empty: \"尚未签名\",\n signed: \"已签名\",\n undo: \"撤销上一笔\",\n clear: \"清除\",\n save: \"保存签名\",\n useTyped: \"改为输入姓名\",\n useDrawn: \"改为手写\",\n typedName: \"姓名\",\n cleared: \"签名已清除\",\n undone: \"已撤销上一笔\",\n viewEmpty: \"未签名\",\n viewDrawn: \"手写签名\",\n // Quoted, so the spacing rule holds whether the name is Han or Latin.\n viewTyped: (name) => `以输入的姓名“${name}”签名`,\n },\n passwordStrength: {\n tooShort: \"太短\",\n weak: \"弱\",\n fair: \"一般\",\n good: \"良好\",\n strong: \"强\",\n announcement: (level) => `密码强度:${level}`,\n // Unformatted, as in the English default.\n ruleLength: (minLength) => `至少 ${minLength} 个字符`,\n ruleCase: \"包含大写和小写字母\",\n ruleDigit: \"包含数字\",\n ruleSymbol: \"包含符号\",\n optional: (rule) => `${rule}(可选)`,\n met: \"已满足:\",\n notMet: \"未满足:\",\n tooLong: (maxBytes) => `最多 ${maxBytes} 个字符(带重音的字母和表情符号按多个字符计算)。`,\n },\n seriesChart: {\n resetZoom: \"重置缩放\",\n zoomHint:\n \"拖动以缩放:近似正方形的选区同时缩放两条坐标轴,细长的选区只缩放其所沿的那条轴。双击可重置。\",\n empty: \"无数据\",\n legend: \"数据系列\",\n points: \"图表数值\",\n },\n pieChart: {\n slices: \"图表扇区\",\n slice: (label, value, percent) => `${label}:${value}(${percent})`,\n total: \"合计\",\n empty: \"无数据\",\n legend: \"类别\",\n },\n confirmDialog: {\n confirm: \"确认\",\n cancel: \"取消\",\n },\n floatingPanel: {\n close: \"关闭\",\n badge: (count) => `${n(count)} 条新内容`,\n },\n copyButton: {\n copy: \"复制\",\n copied: \"已复制\",\n failed: \"复制失败\",\n copiedAnnouncement: \"已复制到剪贴板\",\n failedAnnouncement: \"无法复制到剪贴板\",\n },\n list: {\n unread: \"未读\",\n opensInNewTab: \"在新标签页中打开\",\n },\n breadcrumbs: {\n label: \"面包屑导航\",\n showAll: \"显示完整路径\",\n },\n toast: {\n close: \"关闭通知\",\n notifications: \"通知\",\n undo: \"撤销\",\n redo: \"重做\",\n },\n form: {\n save: \"保存\",\n cancel: \"取消\",\n },\n descriptionList: {\n empty: \"—\",\n },\n lineItems: {\n add: \"添加行\",\n remove: (row) => `删除第 ${row} 行`,\n confirmRemove: (row) => `删除第 ${row} 行?再次按下以确认`,\n row: (row) => `第 ${row} 行`,\n cell: (column, row) => `${column},第 ${row} 行`,\n totals: \"合计\",\n },\n progressBar: {\n unlimited: \"无限制\",\n overLimit: (amount) => `超出限额 ${amount}`,\n },\n signedAmount: {\n positive: (amount) => `正 ${amount}`,\n negative: (amount) => `负 ${amount}`,\n },\n errorBoundary: {\n title: \"出错了\",\n message: \"无法显示页面的这一部分。请重试或重新加载页面。\",\n retry: \"重试\",\n details: \"错误详情\",\n reload: \"重新加载\",\n updateTitle: \"有新版本可用\",\n updateMessage: \"自此页面加载以来,应用的部分内容已更新。请重新加载以获取新版本。\",\n offlineTitle: \"当前处于离线状态\",\n offlineMessage: \"没有网络连接,无法加载此页面。请恢复连接后重新加载页面。\",\n copyReport: \"复制错误报告\",\n reported: \"此错误已自动报告。\",\n reportedAs: (reference) => `报告编号:${reference}`,\n },\n authedImage: {\n loading: \"正在加载图片…\",\n loadError: \"无法加载图片\",\n failedImage: (alt) => `${alt}:无法加载图片`,\n },\n imageGrid: {\n list: \"图片\",\n item: (index, count) => `第 ${n(index)} 张,共 ${n(count)} 张`,\n actions: (name) => `${name}的操作`,\n },\n lightbox: {\n dialog: \"图片查看器\",\n close: \"关闭\",\n previous: \"上一张\",\n next: \"下一张\",\n counter: (index, count) => `${n(index)} / ${n(count)}`,\n position: (index, count) => `第 ${n(index)} 张,共 ${n(count)} 张`,\n download: \"下载\",\n zoom: \"缩放\",\n noPreview: \"此文件无法预览\",\n openInNewTab: \"在新标签页中打开\",\n },\n };\n}\n\nexport const UI_KIT_LABELS_ZH: UiKitLabels = uiKitLabelsZh();\n"],"mappings":"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","names":[]}
|
package/dist/index.d.ts
CHANGED
|
@@ -113,7 +113,7 @@ export { DEFAULT_LIST_LABELS, List, ListDensity, ListItem, ListItemLinkProps, Li
|
|
|
113
113
|
export { MenuItem, MenuItemLinkProps, MenuItemProps, MenuItemTone } from './components/menu-item.js';
|
|
114
114
|
export { CAPTION_CLASS, Caption, CaptionProps, SECTION_LABEL_CLASS, SectionLabel, SectionLabelProps, SectionLabelSize, SectionLabelVariant } from './components/text.js';
|
|
115
115
|
export { StatusDot, StatusDotProps, StatusDotSize, StatusDotTone } from './components/status-dot.js';
|
|
116
|
-
export { PageHeader, PageHeaderMobileLayout, PageHeaderProps, PageHeaderSize } from './components/page-header.js';
|
|
116
|
+
export { PageHeader, PageHeaderActionsAlign, PageHeaderMobileLayout, PageHeaderProps, PageHeaderSize } from './components/page-header.js';
|
|
117
117
|
export { BreadcrumbItem, BreadcrumbLinkProps, Breadcrumbs, BreadcrumbsLabels, BreadcrumbsProps, DEFAULT_BREADCRUMBS_LABELS } from './components/breadcrumbs.js';
|
|
118
118
|
export { TextLink, TextLinkCurrent, TextLinkProps, TextLinkRenderProps, TextLinkTone, TextLinkUnderline } from './components/text-link.js';
|
|
119
119
|
export { DEFAULT_TOAST_LABELS, TOAST_ACTION_DURATION, ToastAction, ToastId, ToastLabels, ToastOptions, ToastPosition, ToastPromiseOptions, ToastRedoOptions, ToastSwipeDirection, ToastUndoOptions, Toaster, ToasterOffset, ToasterProps, toast } from './components/toast.js';
|
|
@@ -134,7 +134,7 @@ export { AuthLayout, AuthLayoutProps } from './shell/auth-layout.js';
|
|
|
134
134
|
export { DEFAULT_ATTACHMENT_ACCEPT, DEFAULT_FEEDBACK_ATTACHMENT_LABELS, DEFAULT_MAX_ATTACHMENT_BYTES, FeedbackAttachmentField, FeedbackAttachmentFieldLabels, pastedName } from './feedback/feedback-attachment.js';
|
|
135
135
|
export { DEFAULT_FEEDBACK_DIALOG_LABELS, FeedbackAttachmentLabels, FeedbackCategoryOption, FeedbackDialog, FeedbackDialogLabels, FeedbackDialogTextLabels, FeedbackSubmission } from './feedback/feedback-dialog.js';
|
|
136
136
|
export { FEEDBACK_CATEGORY_META, FEEDBACK_CATEGORY_ORDER, FEEDBACK_STATUS_META, FEEDBACK_STATUS_ORDER, FeedbackCategory, FeedbackCategoryBadge, FeedbackDetail, FeedbackDetailSection, FeedbackNoteAttachment, FeedbackNoteEditor, FeedbackProse, FeedbackStatus, FeedbackStatusBadge, FeedbackStatusTransitions, feedbackCategoryRank, nextFeedbackStatus, selectableFeedbackStatuses, visibleFeedbackStatuses } from './feedback/feedback-inbox.js';
|
|
137
|
-
export { DEFAULT_FEEDBACK_COMPOSER_LABELS, DEFAULT_FEEDBACK_THREAD_LABELS, FeedbackComposer, FeedbackComposerAttachment, FeedbackComposerHandle, FeedbackComposerLabels, FeedbackComposerProps, FeedbackThread, FeedbackThreadAttachment, FeedbackThreadLabels, FeedbackThreadMessage, FeedbackThreadProps } from './feedback/feedback-thread.js';
|
|
137
|
+
export { DEFAULT_FEEDBACK_COMPOSER_LABELS, DEFAULT_FEEDBACK_THREAD_LABELS, FeedbackComposer, FeedbackComposerAttachment, FeedbackComposerHandle, FeedbackComposerLabels, FeedbackComposerProps, FeedbackThread, FeedbackThreadAttachment, FeedbackThreadEvent, FeedbackThreadItem, FeedbackThreadLabels, FeedbackThreadMessage, FeedbackThreadProps } from './feedback/feedback-thread.js';
|
|
138
138
|
export { DEFAULT_WIZARD_LABELS, FieldErrors, StepStatus, SummaryItem, SummarySection, UseWizardOptions, UseWizardReturn, ValidateResult, WizardLabels, WizardStepConfig, WizardUrlSync, resolveWizardLabels } from './wizard/types.js';
|
|
139
139
|
export { useWizard } from './wizard/use-wizard.js';
|
|
140
140
|
export { WizardContextProvider, WizardContextValue, useOptionalWizardContext, useWizardContext, useWizardNextGate, useWizardStepValidate } from './wizard/wizard-context.js';
|
package/dist/lib/format.js
CHANGED
|
@@ -31,7 +31,7 @@ function numberOptions(o) {
|
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
33
|
function isMissing(value) {
|
|
34
|
-
return value === null || value === void 0 || Number.
|
|
34
|
+
return value === null || value === void 0 || !Number.isFinite(value);
|
|
35
35
|
}
|
|
36
36
|
function formatNumber(value, options = {}) {
|
|
37
37
|
if (isMissing(value)) return options.empty ?? EMPTY_FORMATTED_VALUE;
|
package/dist/lib/format.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/lib/format.ts"],"sourcesContent":["import { useMemo } from \"react\";\nimport { useKitLocale } from \"../i18n/kit-labels\";\nimport { parseIsoDate } from \"./dates\";\n\n/**\n * Number, money, percentage, date and relative-time formatting — `Intl`, in one place,\n * for the figures an app prints OUTSIDE a kit component.\n *\n * Each app grew its own: kastlan's `utils/formatters.ts` (a Swiss-pinned\n * `formatNumber`/`formatCurrency`, a date-fns `formatDate`, and a `formatRelativeTime`\n * whose \"5m ago\" / \"3h ago\" / \"2d ago\" stayed English in every language), its tenancy\n * `format.ts` (`formatChf`, a `formatPct` gluing a \"+\" onto `toFixed(2)`), keksdose's\n * own set. Every one of them is `Intl` with a locale bolted on, so the only thing\n * worth sharing is the locale — and the kit already has one, the provider's.\n *\n * The plain functions take a `locale` (none: the runtime default, as every `Intl` API\n * reads `undefined`). Inside a component, {@link useKitFormat} hands back the same\n * functions bound to the `<UiKitProvider locale>`, so a page formats exactly like the\n * kit components on it.\n *\n * A missing value — `null`, `undefined`, `NaN`, an unparseable date — formats as\n * `empty` (default \"—\", the dash `StatTile` shows for no value), never as \"NaN\" or\n * \"Invalid Date\".\n */\n\n/** What every formatter here prints for a missing value, unless told otherwise. */\nexport const EMPTY_FORMATTED_VALUE = \"—\";\n\n/** Fraction digits: a number pins both the minimum and the maximum (`2` → \"3.10\");\n * an object sets them apart (a meter reading, 1–3). */\nexport type FormatDigits = number | { min?: number; max?: number };\n\ninterface BaseOptions {\n /** BCP 47 tag. Left out: the runtime default (the hook: the provider's). */\n locale?: string;\n /** Printed for a missing value. Default {@link EMPTY_FORMATTED_VALUE}. */\n empty?: string;\n}\n\n/** The options every number formatter shares (money and percent carry their own unit). */\nexport interface FormatNumberBaseOptions extends BaseOptions {\n digits?: FormatDigits;\n /** Compact notation: 12 400 → \"12K\". */\n compact?: boolean;\n /** `\"exceptZero\"` for a change (\"+3\", \"−3\", \"0\"). Default: the minus only. */\n signDisplay?: Intl.NumberFormatOptions[\"signDisplay\"];\n /** Any further `Intl.NumberFormat` options, merged over the ones above. */\n options?: Intl.NumberFormatOptions;\n}\n\n/** The options {@link formatNumber} takes: the shared ones plus a free-text `unit`. */\nexport interface FormatNumberOptions extends FormatNumberBaseOptions {\n /**\n * A unit printed after the figure, joined by a narrow no-break space (U+202F):\n * \"3.400 N\", \"12 kg\", \"4,5 m²\". lenkbank (P8) prints forces, masses and lengths in\n * every table and summary, and each call site glued `${n} N` together with a plain\n * space — which wraps the \"N\" onto the next line in a narrow column and reads loose\n * beside the digit grouping. The narrow no-break space is the SI brochure's and the\n * Swiss typesetting rule's separator between value and unit, and it never breaks.\n *\n * Free text, not `Intl`'s `style: \"unit\"`: that one only knows the ECMA-402\n * sanctioned units (no \"N\", no \"kN\", no \"m³/h\"), so an app would still be gluing.\n * A missing value prints `empty` ALONE — \"— N\" says there is a newton-shaped\n * nothing, which is noise in a column that already heads its unit.\n */\n unit?: string;\n}\n\n/** Narrow no-break space (U+202F): between a figure and its {@link FormatNumberOptions.unit}. */\nconst UNIT_SEPARATOR = \"\\u202F\";\n\nexport interface FormatMoneyOptions extends FormatNumberBaseOptions {\n /** `\"symbol\"` (default), `\"narrowSymbol\"`, `\"code\"` (\"CHF 12.00\") or `\"name\"`. */\n currencyDisplay?: Intl.NumberFormatOptions[\"currencyDisplay\"];\n}\n\nexport interface FormatPercentOptions extends FormatNumberBaseOptions {\n /**\n * `true` (default): `value` is a RATIO, as `Intl` and `StatTile`'s percent delta read\n * it — `0.12` is 12 %. `false`: it is already a percentage — `12` is 12 %\n * (kastlan's rent `change_pct`).\n */\n ratio?: boolean;\n}\n\n// One formatter per option set: a table formats the same way thousands of times, and\n// constructing an Intl formatter is the expensive part.\nconst numberFormatters = new Map<string, Intl.NumberFormat>();\nfunction numberFormatter(locale: string | undefined, options: Intl.NumberFormatOptions): Intl.NumberFormat {\n const key = `${locale ?? \"\"}|${JSON.stringify(options)}`;\n let f = numberFormatters.get(key);\n if (!f) {\n f = new Intl.NumberFormat(locale, options);\n numberFormatters.set(key, f);\n }\n return f;\n}\n\nfunction digitOptions(digits: FormatDigits | undefined): Intl.NumberFormatOptions {\n if (digits === undefined) return {};\n if (typeof digits === \"number\") return { minimumFractionDigits: digits, maximumFractionDigits: digits };\n return {\n ...(digits.min !== undefined ? { minimumFractionDigits: digits.min } : null),\n ...(digits.max !== undefined ? { maximumFractionDigits: digits.max } : null),\n };\n}\n\nfunction numberOptions(o: FormatNumberBaseOptions): Intl.NumberFormatOptions {\n return {\n ...digitOptions(o.digits),\n ...(o.compact ? { notation: \"compact\" } : null),\n ...(o.signDisplay ? { signDisplay: o.signDisplay } : null),\n ...o.options,\n };\n}\n\nfunction isMissing(value: number | null | undefined): value is null | undefined {\n return value === null || value === undefined || Number.isNaN(value);\n}\n\n/** A number in `locale`: \"1,234.5\", \"1.234,5\", \"1’234.5\" — with `unit`, \"3.400 N\". */\nexport function formatNumber(value: number | null | undefined, options: FormatNumberOptions = {}): string {\n if (isMissing(value)) return options.empty ?? EMPTY_FORMATTED_VALUE;\n const figure = numberFormatter(options.locale, numberOptions(options)).format(value);\n return options.unit ? `${figure}${UNIT_SEPARATOR}${options.unit}` : figure;\n}\n\n/** An amount of `currency` (ISO 4217) in `locale`: \"CHF 1’234.50\", \"1.234,50 €\". */\nexport function formatMoney(\n value: number | null | undefined,\n currency: string,\n options: FormatMoneyOptions = {},\n): string {\n if (isMissing(value)) return options.empty ?? EMPTY_FORMATTED_VALUE;\n return numberFormatter(options.locale, {\n style: \"currency\",\n currency,\n ...(options.currencyDisplay ? { currencyDisplay: options.currencyDisplay } : null),\n ...numberOptions(options),\n }).format(value);\n}\n\n/** A percentage in `locale` (\"12%\", \"12 %\", \"+1.25%\"). See {@link FormatPercentOptions.ratio}\n * for what `value` means. Default digits: at most one. */\nexport function formatPercent(value: number | null | undefined, options: FormatPercentOptions = {}): string {\n if (isMissing(value)) return options.empty ?? EMPTY_FORMATTED_VALUE;\n const ratio = options.ratio === false ? value / 100 : value;\n return numberFormatter(options.locale, {\n style: \"percent\",\n ...(options.digits === undefined ? { maximumFractionDigits: 1 } : null),\n ...numberOptions(options),\n }).format(ratio);\n}\n\n/* ── Dates ─────────────────────────────────────────────────────────────────── */\n\n/**\n * The shapes a date is printed in, each a set of `Intl.DateTimeFormat` options:\n * - `short` / `medium` / `long` / `full` — the date alone, at that `dateStyle`\n * (\"08/07/2026\", \"8 Jul 2026\", \"8 July 2026\", \"Wednesday, 8 July 2026\" in en-GB).\n * - `dateTime` — medium date and short time: a timestamp (\"8 Jul 2026, 14:05\").\n * - `time` — the short time alone (\"14:05\").\n * - `monthYear` — \"July 2026\".\n *\n * Or pass `Intl.DateTimeFormatOptions` for anything else. A date-fns PATTERN\n * (\"dd.MM.yyyy\") is deliberately not accepted: a pattern is one locale's order baked\n * into a string, which is how an English page ends up with German dates.\n */\nexport type FormatDateStyle = \"short\" | \"medium\" | \"long\" | \"full\" | \"dateTime\" | \"time\" | \"monthYear\";\n\nconst DATE_STYLES: Record<FormatDateStyle, Intl.DateTimeFormatOptions> = {\n short: { dateStyle: \"short\" },\n medium: { dateStyle: \"medium\" },\n long: { dateStyle: \"long\" },\n full: { dateStyle: \"full\" },\n dateTime: { dateStyle: \"medium\", timeStyle: \"short\" },\n time: { timeStyle: \"short\" },\n monthYear: { month: \"long\", year: \"numeric\" },\n};\n\nexport interface FormatDateOptions extends BaseOptions {\n /** An IANA zone (\"Europe/Zurich\") for a timestamp. Left out: the device's. */\n timeZone?: string;\n}\n\n/** What {@link formatDate} and {@link formatRelativeTime} accept. */\nexport type DateInput = string | number | Date | null | undefined;\n\n/**\n * `value` as a Date, or null. A bare \"YYYY-MM-DD\" is a CALENDAR day and is read on the\n * local calendar (`parseIsoDate`) — `new Date(\"2026-07-08\")` is UTC midnight, which is\n * the 7th anywhere west of Greenwich. Anything else (a full ISO timestamp, epoch\n * milliseconds, a Date) is an instant and goes through `Date` as is.\n */\nexport function toDate(value: DateInput): Date | null {\n if (value === null || value === undefined || value === \"\") return null;\n if (typeof value === \"string\" && /^\\d{4}-\\d{2}-\\d{2}$/.test(value)) return parseIsoDate(value);\n const d = value instanceof Date ? value : new Date(value);\n return Number.isNaN(d.getTime()) ? null : d;\n}\n\nconst dateFormatters = new Map<string, Intl.DateTimeFormat>();\nfunction dateFormatter(locale: string | undefined, options: Intl.DateTimeFormatOptions): Intl.DateTimeFormat {\n const key = `${locale ?? \"\"}|${JSON.stringify(options)}`;\n let f = dateFormatters.get(key);\n if (!f) {\n f = new Intl.DateTimeFormat(locale, options);\n dateFormatters.set(key, f);\n }\n return f;\n}\n\n/**\n * A date or timestamp in `locale`. Takes an ISO date (\"2026-07-08\", read on the local\n * calendar), an ISO timestamp (\"2026-07-08T14:05:00Z\"), epoch milliseconds or a Date.\n * `style` defaults to `medium`; see {@link FormatDateStyle}.\n *\n * `formatIsoDate` (`@eifi1/ui-kit/dates`) remains for a plain \"YYYY-MM-DD\" with an\n * explicit locale; this is its superset for timestamps and the named styles.\n */\nexport function formatDate(\n value: DateInput,\n style: FormatDateStyle | Intl.DateTimeFormatOptions = \"medium\",\n options: FormatDateOptions = {},\n): string {\n const d = toDate(value);\n if (!d) return options.empty ?? EMPTY_FORMATTED_VALUE;\n const base = typeof style === \"string\" ? DATE_STYLES[style] : style;\n return dateFormatter(options.locale, options.timeZone ? { ...base, timeZone: options.timeZone } : base).format(d);\n}\n\nexport interface FormatRelativeTimeOptions extends BaseOptions {\n /** The moment it is measured from. Default: now. */\n now?: DateInput;\n /** `\"auto\"` (default): \"yesterday\", \"now\", \"next week\". `\"always\"`: \"1 day ago\". */\n numeric?: Intl.RelativeTimeFormatNumeric;\n /** `\"long\"` (default) \"3 hours ago\", `\"short\"` \"3 hr. ago\", `\"narrow\"` \"3h ago\". */\n style?: Intl.RelativeTimeFormatStyle;\n /**\n * Past this many days either way, print the date instead ({@link formatDate} in\n * `absoluteStyle`) — kastlan's feed switches to the date after a week, because \"5\n * weeks ago\" makes a reader do sums. Default: never.\n */\n absoluteAfterDays?: number;\n /** The style of that date. Default `medium`. */\n absoluteStyle?: FormatDateStyle | Intl.DateTimeFormatOptions;\n}\n\nconst SECOND = 1000;\nconst MINUTE = 60 * SECOND;\nconst HOUR = 60 * MINUTE;\nconst DAY = 24 * HOUR;\n\n/** [the largest |difference| a unit is used for, the unit, its length]. */\nconst RELATIVE_STEPS: Array<[number, Intl.RelativeTimeFormatUnit, number]> = [\n [45 * SECOND, \"second\", SECOND],\n [45 * MINUTE, \"minute\", MINUTE],\n [22 * HOUR, \"hour\", HOUR],\n [6.5 * DAY, \"day\", DAY],\n [26 * DAY, \"week\", 7 * DAY],\n [320 * DAY, \"month\", 30.44 * DAY],\n [Infinity, \"year\", 365.25 * DAY],\n];\n\nconst relativeFormatters = new Map<string, Intl.RelativeTimeFormat>();\nfunction relativeFormatter(\n locale: string | undefined,\n numeric: Intl.RelativeTimeFormatNumeric,\n style: Intl.RelativeTimeFormatStyle,\n): Intl.RelativeTimeFormat {\n const key = `${locale ?? \"\"}|${numeric}|${style}`;\n let f = relativeFormatters.get(key);\n if (!f) {\n f = new Intl.RelativeTimeFormat(locale, { numeric, style });\n relativeFormatters.set(key, f);\n }\n return f;\n}\n\n/**\n * How long ago (or until) `value` is, in `locale`'s words, through\n * `Intl.RelativeTimeFormat`: \"3 hours ago\", \"vor 3 Stunden\", \"il y a 3 heures\",\n * \"in 2 days\", and under 45 seconds \"now\". The unit is picked by size — seconds,\n * minutes, hours, days, weeks, months, years — and the count is rounded.\n */\nexport function formatRelativeTime(value: DateInput, options: FormatRelativeTimeOptions = {}): string {\n const d = toDate(value);\n if (!d) return options.empty ?? EMPTY_FORMATTED_VALUE;\n const now = toDate(options.now ?? new Date()) ?? new Date();\n const diff = d.getTime() - now.getTime();\n const abs = Math.abs(diff);\n if (options.absoluteAfterDays !== undefined && abs > options.absoluteAfterDays * DAY) {\n return formatDate(d, options.absoluteStyle ?? \"medium\", options);\n }\n const rtf = relativeFormatter(options.locale, options.numeric ?? \"auto\", options.style ?? \"long\");\n const [, unit, size] = RELATIVE_STEPS.find(([limit]) => abs < limit)!;\n // Under 45 seconds is \"now\" rather than \"12 seconds ago\": a feed that ticks through\n // the seconds is noise, and nothing reads a timestamp to the second.\n const count = unit === \"second\" ? 0 : Math.round(diff / size);\n // `+ 0` folds -0 into 0: `format(-0, …)` says \"0 seconds ago\" instead of \"now\".\n return rtf.format(count + 0, unit);\n}\n\n/* ── Bound to the provider ─────────────────────────────────────────────────── */\n\ntype WithoutLocale<T> = Omit<T, \"locale\"> & { locale?: string };\n\n/** What {@link useKitFormat} returns: the formatters above with the provider's locale\n * as their default (an explicit `locale` in the options still wins). */\nexport interface KitFormat {\n /** The locale they format in — the provider's, or `undefined` (runtime default). */\n locale: string | undefined;\n formatNumber: (value: number | null | undefined, options?: WithoutLocale<FormatNumberOptions>) => string;\n formatMoney: (\n value: number | null | undefined,\n currency: string,\n options?: WithoutLocale<FormatMoneyOptions>,\n ) => string;\n formatPercent: (value: number | null | undefined, options?: WithoutLocale<FormatPercentOptions>) => string;\n formatDate: (\n value: DateInput,\n style?: FormatDateStyle | Intl.DateTimeFormatOptions,\n options?: WithoutLocale<FormatDateOptions>,\n ) => string;\n formatRelativeTime: (value: DateInput, options?: WithoutLocale<FormatRelativeTimeOptions>) => string;\n}\n\n/**\n * The formatters, bound to the `<UiKitProvider locale>` (or to `locale`, which wins\n * over it — the same precedence as a component's `locale` prop):\n *\n * const { formatMoney, formatRelativeTime } = useKitFormat();\n * formatMoney(row.balance, \"CHF\");\n */\nexport function useKitFormat(locale?: string): KitFormat {\n const kitLocale = useKitLocale(locale);\n return useMemo<KitFormat>(\n () => ({\n locale: kitLocale,\n formatNumber: (value, options) => formatNumber(value, { locale: kitLocale, ...options }),\n formatMoney: (value, currency, options) => formatMoney(value, currency, { locale: kitLocale, ...options }),\n formatPercent: (value, options) => formatPercent(value, { locale: kitLocale, ...options }),\n formatDate: (value, style, options) => formatDate(value, style, { locale: kitLocale, ...options }),\n formatRelativeTime: (value, options) => formatRelativeTime(value, { locale: kitLocale, ...options }),\n }),\n [kitLocale],\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/lib/format.ts"],"sourcesContent":["import { useMemo } from \"react\";\nimport { useKitLocale } from \"../i18n/kit-labels\";\nimport { parseIsoDate } from \"./dates\";\n\n/**\n * Number, money, percentage, date and relative-time formatting — `Intl`, in one place,\n * for the figures an app prints OUTSIDE a kit component.\n *\n * Each app grew its own: kastlan's `utils/formatters.ts` (a Swiss-pinned\n * `formatNumber`/`formatCurrency`, a date-fns `formatDate`, and a `formatRelativeTime`\n * whose \"5m ago\" / \"3h ago\" / \"2d ago\" stayed English in every language), its tenancy\n * `format.ts` (`formatChf`, a `formatPct` gluing a \"+\" onto `toFixed(2)`), keksdose's\n * own set. Every one of them is `Intl` with a locale bolted on, so the only thing\n * worth sharing is the locale — and the kit already has one, the provider's.\n *\n * The plain functions take a `locale` (none: the runtime default, as every `Intl` API\n * reads `undefined`). Inside a component, {@link useKitFormat} hands back the same\n * functions bound to the `<UiKitProvider locale>`, so a page formats exactly like the\n * kit components on it.\n *\n * A missing value — `null`, `undefined`, `NaN`, an unparseable date — formats as\n * `empty` (default \"—\", the dash `StatTile` shows for no value), never as \"NaN\" or\n * \"Invalid Date\".\n */\n\n/** What every formatter here prints for a missing value, unless told otherwise. */\nexport const EMPTY_FORMATTED_VALUE = \"—\";\n\n/** Fraction digits: a number pins both the minimum and the maximum (`2` → \"3.10\");\n * an object sets them apart (a meter reading, 1–3). */\nexport type FormatDigits = number | { min?: number; max?: number };\n\ninterface BaseOptions {\n /** BCP 47 tag. Left out: the runtime default (the hook: the provider's). */\n locale?: string;\n /** Printed for a missing value. Default {@link EMPTY_FORMATTED_VALUE}. */\n empty?: string;\n}\n\n/** The options every number formatter shares (money and percent carry their own unit). */\nexport interface FormatNumberBaseOptions extends BaseOptions {\n digits?: FormatDigits;\n /** Compact notation: 12 400 → \"12K\". */\n compact?: boolean;\n /** `\"exceptZero\"` for a change (\"+3\", \"−3\", \"0\"). Default: the minus only. */\n signDisplay?: Intl.NumberFormatOptions[\"signDisplay\"];\n /** Any further `Intl.NumberFormat` options, merged over the ones above. */\n options?: Intl.NumberFormatOptions;\n}\n\n/** The options {@link formatNumber} takes: the shared ones plus a free-text `unit`. */\nexport interface FormatNumberOptions extends FormatNumberBaseOptions {\n /**\n * A unit printed after the figure, joined by a narrow no-break space (U+202F):\n * \"3.400 N\", \"12 kg\", \"4,5 m²\". lenkbank (P8) prints forces, masses and lengths in\n * every table and summary, and each call site glued `${n} N` together with a plain\n * space — which wraps the \"N\" onto the next line in a narrow column and reads loose\n * beside the digit grouping. The narrow no-break space is the SI brochure's and the\n * Swiss typesetting rule's separator between value and unit, and it never breaks.\n *\n * Free text, not `Intl`'s `style: \"unit\"`: that one only knows the ECMA-402\n * sanctioned units (no \"N\", no \"kN\", no \"m³/h\"), so an app would still be gluing.\n * A missing value prints `empty` ALONE — \"— N\" says there is a newton-shaped\n * nothing, which is noise in a column that already heads its unit.\n */\n unit?: string;\n}\n\n/** Narrow no-break space (U+202F): between a figure and its {@link FormatNumberOptions.unit}. */\nconst UNIT_SEPARATOR = \"\\u202F\";\n\nexport interface FormatMoneyOptions extends FormatNumberBaseOptions {\n /** `\"symbol\"` (default), `\"narrowSymbol\"`, `\"code\"` (\"CHF 12.00\") or `\"name\"`. */\n currencyDisplay?: Intl.NumberFormatOptions[\"currencyDisplay\"];\n}\n\nexport interface FormatPercentOptions extends FormatNumberBaseOptions {\n /**\n * `true` (default): `value` is a RATIO, as `Intl` and `StatTile`'s percent delta read\n * it — `0.12` is 12 %. `false`: it is already a percentage — `12` is 12 %\n * (kastlan's rent `change_pct`).\n */\n ratio?: boolean;\n}\n\n// One formatter per option set: a table formats the same way thousands of times, and\n// constructing an Intl formatter is the expensive part.\nconst numberFormatters = new Map<string, Intl.NumberFormat>();\nfunction numberFormatter(locale: string | undefined, options: Intl.NumberFormatOptions): Intl.NumberFormat {\n const key = `${locale ?? \"\"}|${JSON.stringify(options)}`;\n let f = numberFormatters.get(key);\n if (!f) {\n f = new Intl.NumberFormat(locale, options);\n numberFormatters.set(key, f);\n }\n return f;\n}\n\nfunction digitOptions(digits: FormatDigits | undefined): Intl.NumberFormatOptions {\n if (digits === undefined) return {};\n if (typeof digits === \"number\") return { minimumFractionDigits: digits, maximumFractionDigits: digits };\n return {\n ...(digits.min !== undefined ? { minimumFractionDigits: digits.min } : null),\n ...(digits.max !== undefined ? { maximumFractionDigits: digits.max } : null),\n };\n}\n\nfunction numberOptions(o: FormatNumberBaseOptions): Intl.NumberFormatOptions {\n return {\n ...digitOptions(o.digits),\n ...(o.compact ? { notation: \"compact\" } : null),\n ...(o.signDisplay ? { signDisplay: o.signDisplay } : null),\n ...o.options,\n };\n}\n\nfunction isMissing(value: number | null | undefined): value is null | undefined {\n // ±Infinity too (lenkbank, adopting 0.13): a division by zero upstream is a missing\n // figure, and \"∞\" printed in a money or measurement column reads like data.\n return value === null || value === undefined || !Number.isFinite(value);\n}\n\n/** A number in `locale`: \"1,234.5\", \"1.234,5\", \"1’234.5\" — with `unit`, \"3.400 N\". */\nexport function formatNumber(value: number | null | undefined, options: FormatNumberOptions = {}): string {\n if (isMissing(value)) return options.empty ?? EMPTY_FORMATTED_VALUE;\n const figure = numberFormatter(options.locale, numberOptions(options)).format(value);\n return options.unit ? `${figure}${UNIT_SEPARATOR}${options.unit}` : figure;\n}\n\n/** An amount of `currency` (ISO 4217) in `locale`: \"CHF 1’234.50\", \"1.234,50 €\". */\nexport function formatMoney(\n value: number | null | undefined,\n currency: string,\n options: FormatMoneyOptions = {},\n): string {\n if (isMissing(value)) return options.empty ?? EMPTY_FORMATTED_VALUE;\n return numberFormatter(options.locale, {\n style: \"currency\",\n currency,\n ...(options.currencyDisplay ? { currencyDisplay: options.currencyDisplay } : null),\n ...numberOptions(options),\n }).format(value);\n}\n\n/** A percentage in `locale` (\"12%\", \"12 %\", \"+1.25%\"). See {@link FormatPercentOptions.ratio}\n * for what `value` means. Default digits: at most one. */\nexport function formatPercent(value: number | null | undefined, options: FormatPercentOptions = {}): string {\n if (isMissing(value)) return options.empty ?? EMPTY_FORMATTED_VALUE;\n const ratio = options.ratio === false ? value / 100 : value;\n return numberFormatter(options.locale, {\n style: \"percent\",\n ...(options.digits === undefined ? { maximumFractionDigits: 1 } : null),\n ...numberOptions(options),\n }).format(ratio);\n}\n\n/* ── Dates ─────────────────────────────────────────────────────────────────── */\n\n/**\n * The shapes a date is printed in, each a set of `Intl.DateTimeFormat` options:\n * - `short` / `medium` / `long` / `full` — the date alone, at that `dateStyle`\n * (\"08/07/2026\", \"8 Jul 2026\", \"8 July 2026\", \"Wednesday, 8 July 2026\" in en-GB).\n * - `dateTime` — medium date and short time: a timestamp (\"8 Jul 2026, 14:05\").\n * - `time` — the short time alone (\"14:05\").\n * - `monthYear` — \"July 2026\".\n *\n * Or pass `Intl.DateTimeFormatOptions` for anything else. A date-fns PATTERN\n * (\"dd.MM.yyyy\") is deliberately not accepted: a pattern is one locale's order baked\n * into a string, which is how an English page ends up with German dates.\n */\nexport type FormatDateStyle = \"short\" | \"medium\" | \"long\" | \"full\" | \"dateTime\" | \"time\" | \"monthYear\";\n\nconst DATE_STYLES: Record<FormatDateStyle, Intl.DateTimeFormatOptions> = {\n short: { dateStyle: \"short\" },\n medium: { dateStyle: \"medium\" },\n long: { dateStyle: \"long\" },\n full: { dateStyle: \"full\" },\n dateTime: { dateStyle: \"medium\", timeStyle: \"short\" },\n time: { timeStyle: \"short\" },\n monthYear: { month: \"long\", year: \"numeric\" },\n};\n\nexport interface FormatDateOptions extends BaseOptions {\n /** An IANA zone (\"Europe/Zurich\") for a timestamp. Left out: the device's. */\n timeZone?: string;\n}\n\n/** What {@link formatDate} and {@link formatRelativeTime} accept. */\nexport type DateInput = string | number | Date | null | undefined;\n\n/**\n * `value` as a Date, or null. A bare \"YYYY-MM-DD\" is a CALENDAR day and is read on the\n * local calendar (`parseIsoDate`) — `new Date(\"2026-07-08\")` is UTC midnight, which is\n * the 7th anywhere west of Greenwich. Anything else (a full ISO timestamp, epoch\n * milliseconds, a Date) is an instant and goes through `Date` as is.\n */\nexport function toDate(value: DateInput): Date | null {\n if (value === null || value === undefined || value === \"\") return null;\n if (typeof value === \"string\" && /^\\d{4}-\\d{2}-\\d{2}$/.test(value)) return parseIsoDate(value);\n const d = value instanceof Date ? value : new Date(value);\n return Number.isNaN(d.getTime()) ? null : d;\n}\n\nconst dateFormatters = new Map<string, Intl.DateTimeFormat>();\nfunction dateFormatter(locale: string | undefined, options: Intl.DateTimeFormatOptions): Intl.DateTimeFormat {\n const key = `${locale ?? \"\"}|${JSON.stringify(options)}`;\n let f = dateFormatters.get(key);\n if (!f) {\n f = new Intl.DateTimeFormat(locale, options);\n dateFormatters.set(key, f);\n }\n return f;\n}\n\n/**\n * A date or timestamp in `locale`. Takes an ISO date (\"2026-07-08\", read on the local\n * calendar), an ISO timestamp (\"2026-07-08T14:05:00Z\"), epoch milliseconds or a Date.\n * `style` defaults to `medium`; see {@link FormatDateStyle}.\n *\n * `formatIsoDate` (`@eifi1/ui-kit/dates`) remains for a plain \"YYYY-MM-DD\" with an\n * explicit locale; this is its superset for timestamps and the named styles.\n */\nexport function formatDate(\n value: DateInput,\n style: FormatDateStyle | Intl.DateTimeFormatOptions = \"medium\",\n options: FormatDateOptions = {},\n): string {\n const d = toDate(value);\n if (!d) return options.empty ?? EMPTY_FORMATTED_VALUE;\n const base = typeof style === \"string\" ? DATE_STYLES[style] : style;\n return dateFormatter(options.locale, options.timeZone ? { ...base, timeZone: options.timeZone } : base).format(d);\n}\n\nexport interface FormatRelativeTimeOptions extends BaseOptions {\n /** The moment it is measured from. Default: now. */\n now?: DateInput;\n /** `\"auto\"` (default): \"yesterday\", \"now\", \"next week\". `\"always\"`: \"1 day ago\". */\n numeric?: Intl.RelativeTimeFormatNumeric;\n /** `\"long\"` (default) \"3 hours ago\", `\"short\"` \"3 hr. ago\", `\"narrow\"` \"3h ago\". */\n style?: Intl.RelativeTimeFormatStyle;\n /**\n * Past this many days either way, print the date instead ({@link formatDate} in\n * `absoluteStyle`) — kastlan's feed switches to the date after a week, because \"5\n * weeks ago\" makes a reader do sums. Default: never.\n */\n absoluteAfterDays?: number;\n /** The style of that date. Default `medium`. */\n absoluteStyle?: FormatDateStyle | Intl.DateTimeFormatOptions;\n}\n\nconst SECOND = 1000;\nconst MINUTE = 60 * SECOND;\nconst HOUR = 60 * MINUTE;\nconst DAY = 24 * HOUR;\n\n/** [the largest |difference| a unit is used for, the unit, its length]. */\nconst RELATIVE_STEPS: Array<[number, Intl.RelativeTimeFormatUnit, number]> = [\n [45 * SECOND, \"second\", SECOND],\n [45 * MINUTE, \"minute\", MINUTE],\n [22 * HOUR, \"hour\", HOUR],\n [6.5 * DAY, \"day\", DAY],\n [26 * DAY, \"week\", 7 * DAY],\n [320 * DAY, \"month\", 30.44 * DAY],\n [Infinity, \"year\", 365.25 * DAY],\n];\n\nconst relativeFormatters = new Map<string, Intl.RelativeTimeFormat>();\nfunction relativeFormatter(\n locale: string | undefined,\n numeric: Intl.RelativeTimeFormatNumeric,\n style: Intl.RelativeTimeFormatStyle,\n): Intl.RelativeTimeFormat {\n const key = `${locale ?? \"\"}|${numeric}|${style}`;\n let f = relativeFormatters.get(key);\n if (!f) {\n f = new Intl.RelativeTimeFormat(locale, { numeric, style });\n relativeFormatters.set(key, f);\n }\n return f;\n}\n\n/**\n * How long ago (or until) `value` is, in `locale`'s words, through\n * `Intl.RelativeTimeFormat`: \"3 hours ago\", \"vor 3 Stunden\", \"il y a 3 heures\",\n * \"in 2 days\", and under 45 seconds \"now\". The unit is picked by size — seconds,\n * minutes, hours, days, weeks, months, years — and the count is rounded.\n */\nexport function formatRelativeTime(value: DateInput, options: FormatRelativeTimeOptions = {}): string {\n const d = toDate(value);\n if (!d) return options.empty ?? EMPTY_FORMATTED_VALUE;\n const now = toDate(options.now ?? new Date()) ?? new Date();\n const diff = d.getTime() - now.getTime();\n const abs = Math.abs(diff);\n if (options.absoluteAfterDays !== undefined && abs > options.absoluteAfterDays * DAY) {\n return formatDate(d, options.absoluteStyle ?? \"medium\", options);\n }\n const rtf = relativeFormatter(options.locale, options.numeric ?? \"auto\", options.style ?? \"long\");\n const [, unit, size] = RELATIVE_STEPS.find(([limit]) => abs < limit)!;\n // Under 45 seconds is \"now\" rather than \"12 seconds ago\": a feed that ticks through\n // the seconds is noise, and nothing reads a timestamp to the second.\n const count = unit === \"second\" ? 0 : Math.round(diff / size);\n // `+ 0` folds -0 into 0: `format(-0, …)` says \"0 seconds ago\" instead of \"now\".\n return rtf.format(count + 0, unit);\n}\n\n/* ── Bound to the provider ─────────────────────────────────────────────────── */\n\ntype WithoutLocale<T> = Omit<T, \"locale\"> & { locale?: string };\n\n/** What {@link useKitFormat} returns: the formatters above with the provider's locale\n * as their default (an explicit `locale` in the options still wins). */\nexport interface KitFormat {\n /** The locale they format in — the provider's, or `undefined` (runtime default). */\n locale: string | undefined;\n formatNumber: (value: number | null | undefined, options?: WithoutLocale<FormatNumberOptions>) => string;\n formatMoney: (\n value: number | null | undefined,\n currency: string,\n options?: WithoutLocale<FormatMoneyOptions>,\n ) => string;\n formatPercent: (value: number | null | undefined, options?: WithoutLocale<FormatPercentOptions>) => string;\n formatDate: (\n value: DateInput,\n style?: FormatDateStyle | Intl.DateTimeFormatOptions,\n options?: WithoutLocale<FormatDateOptions>,\n ) => string;\n formatRelativeTime: (value: DateInput, options?: WithoutLocale<FormatRelativeTimeOptions>) => string;\n}\n\n/**\n * The formatters, bound to the `<UiKitProvider locale>` (or to `locale`, which wins\n * over it — the same precedence as a component's `locale` prop):\n *\n * const { formatMoney, formatRelativeTime } = useKitFormat();\n * formatMoney(row.balance, \"CHF\");\n */\nexport function useKitFormat(locale?: string): KitFormat {\n const kitLocale = useKitLocale(locale);\n return useMemo<KitFormat>(\n () => ({\n locale: kitLocale,\n formatNumber: (value, options) => formatNumber(value, { locale: kitLocale, ...options }),\n formatMoney: (value, currency, options) => formatMoney(value, currency, { locale: kitLocale, ...options }),\n formatPercent: (value, options) => formatPercent(value, { locale: kitLocale, ...options }),\n formatDate: (value, style, options) => formatDate(value, style, { locale: kitLocale, ...options }),\n formatRelativeTime: (value, options) => formatRelativeTime(value, { locale: kitLocale, ...options }),\n }),\n [kitLocale],\n );\n}\n"],"mappings":"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","names":[]}
|
package/dist/rhf/fields.d.ts
CHANGED
|
@@ -209,7 +209,9 @@ type RhfMoneyFieldProps<TFieldValues extends FieldValues = FieldValues, TName ex
|
|
|
209
209
|
/** What an emptied field stores when `valueAs` is `"number"`. Default `null`. */
|
|
210
210
|
emptyValue?: null | "";
|
|
211
211
|
/** Decimals the amount settles to on blur, Enter or a calculator result. Default:
|
|
212
|
-
* the currency's minor unit (CHF 2, JPY 0).
|
|
212
|
+
* the currency's minor unit (CHF 2, JPY 0). ⚠️ A unit price or a rate needs its
|
|
213
|
+
* column's scale here (`digits={4}` for 1.789 €/l), or it is stored rounded to
|
|
214
|
+
* cents without a word (keksdose G2). See {@link AmountInput}'s `digits`. */
|
|
213
215
|
digits?: number;
|
|
214
216
|
/** Clamp the settled amount (a release capped at the deposit's balance). Validate
|
|
215
217
|
* with `rules` as well if a clamp needs explaining. */
|
package/dist/rhf/fields.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/rhf/fields.tsx"],"sourcesContent":["/**\n * Bound fields: one line per field of a react-hook-form form. `@eifi1/ui-kit/rhf`.\n *\n * ```tsx\n * <Form {...form}>\n * <RhfTextField name=\"name\" label=\"Name\" hint=\"As on the lease\" required\n * rules={{ required: \"Enter a name\" }} />\n * <RhfMoneyField name=\"rent\" label=\"Net rent\" currency=\"CHF\" />\n * <RhfDateField name=\"start\" label=\"Start\" />\n * <RhfSelect name=\"type\" label=\"Type\" options={TYPES} />\n * <RhfCombobox name=\"tenantId\" label=\"Tenant\" options={tenants} clearable />\n * <RhfCheckbox name=\"isDefault\" label=\"Default account\" />\n * </Form>\n * ```\n *\n * Each folds the `FormField → FormItem → FormLabel → FormControl → field →\n * FormDescription → FormMessage` scaffold (see ./form) into one element, the way\n * kastlan's shared/components/form/fields.tsx does for its forms — with what that file\n * left out:\n *\n * - **The red border.** Every field gets `invalid` from the field state, so an errored\n * field PAINTS as well as announces. kastlan's number, money, date and entity fields\n * passed only `aria-invalid` through `FormControl`, or nothing, and `Input`, `Select`\n * and `Textarea` paint only from the prop (see the note in ./form).\n * - **Focus on error.** `field.ref` reaches the focusable element — the element itself\n * where the kit field forwards a ref, a focus handle on it where it does not (the\n * number field, the pickers) — so `handleSubmit` and `trigger(…, { shouldFocus })`\n * land the caret on the first field in error.\n * - **`control` is optional**: under `<Form {...form}>` the fields find the form\n * through react-hook-form's context. Pass it for the field's value types\n * (`control={form.control}` checks `name` against the form's values).\n *\n * The common props: `name`, `control`, `label` (a {@link FormLabel} above the field;\n * omitted, none — then give the field an `aria-label`), `hint` (standing advice under\n * the field, attached to it with `aria-describedby`), `required` (the label's mark,\n * and `aria-required` where the control takes it — validation is `rules`' or the\n * resolver's), `rules`, `disabled` (the control only — the value is still submitted;\n * `excludeWhenDisabled` for react-hook-form's drop-the-value semantics), and\n * `className` for the item's box.\n *\n * {@link RhfField} is the shell they are all built on, for a control the kit does not\n * ship (an address autocomplete): it takes a `render` and wires the rest.\n */\nimport { useLayoutEffect, useRef, useState, type ReactElement, type ReactNode } from \"react\";\nimport type {\n ControllerFieldState,\n ControllerProps,\n ControllerRenderProps,\n FieldPath,\n FieldValues,\n} from \"react-hook-form\";\nimport { FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, useFormField } from \"./form\";\nimport { Input, Select, Textarea, type InputProps, type SelectProps, type TextareaProps } from \"../components/ui\";\nimport { NumberField, type NumberFieldProps } from \"../components/number-field\";\nimport { AmountInput } from \"../components/amount-input\";\nimport { DatePicker, type DatePickerProps } from \"../components/date-picker\";\nimport { Checkbox, type CheckboxProps } from \"../components/checkbox\";\nimport { EntityCombobox, type EntityComboboxProps } from \"../components/entity-combobox\";\nimport { Combobox, type ComboboxProps } from \"../components/combobox\";\nimport type { ComboClearValue } from \"../components/combobox-core\";\nimport { cn } from \"../lib/cn\";\n\n// ── the shell ────────────────────────────────────────────────────────────────\n\n/** What every bound field takes. */\nexport interface RhfFieldBaseProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> {\n name: TName;\n /** `form.control`. Optional under `<Form {...form}>`; pass it to type-check `name`. */\n control?: ControllerProps<TFieldValues, TName, TTransformed>[\"control\"];\n /** react-hook-form's `rules` (`required`, `min`, `validate` …). */\n rules?: ControllerProps<TFieldValues, TName, TTransformed>[\"rules\"];\n /** A {@link FormLabel} above the field. Omitted: no label — name the control with\n * an `aria-label` instead. */\n label?: ReactNode;\n /** Standing advice under the field (\"As printed on the card\"), attached to the\n * control with `aria-describedby`. */\n hint?: ReactNode;\n /** Draws the label's required mark and sets `aria-required` where the control\n * takes it. Whether the field IS required is `rules`' or the resolver's to say. */\n required?: boolean;\n /** Disables the control and KEEPS the value: a field locked to a preset (a lease's\n * preselected unit, a fixed period) still submits it, and `rules` still run.\n * react-hook-form's own Controller `disabled` drops the value from `handleSubmit`'s\n * data instead, which a locked preset must never do (kastlan, 0.12). To get that,\n * add `excludeWhenDisabled`. A form-wide `useForm({ disabled })` still disables\n * every field the RHF way. */\n disabled?: boolean;\n /** With `disabled`: disable through react-hook-form, so the value is left out of\n * the submitted data and validation skips it, like a disabled native input in a\n * plain form post. Default `false`. */\n excludeWhenDisabled?: boolean;\n /** Classes for the item's box (a `grid gap-1`). */\n className?: string;\n}\n\n/** What {@link RhfField}'s `render` receives. */\nexport interface RhfFieldRenderContext<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n> {\n field: ControllerRenderProps<TFieldValues, TName>;\n fieldState: ControllerFieldState;\n /** The field has an error: pass it to the control's `invalid` so it paints. */\n invalid: boolean;\n /** The error's message, if any. */\n error: string | undefined;\n /** The control's id, which the label points at. `FormControl` sets it on the\n * rendered element already; this is for a control that routes it elsewhere. */\n id: string;\n /** The label's id, for a control that is named with `aria-labelledby`. */\n labelId: string;\n /** The ids of the rendered hint and message, if any. */\n describedBy: string | undefined;\n}\n\nexport interface RhfFieldProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> extends RhfFieldBaseProps<TFieldValues, TName, TTransformed> {\n /** The control. Wrapped in {@link FormControl} (its `id`, `aria-describedby` and\n * `aria-invalid`) unless `asControl` is false. */\n render: (ctx: RhfFieldRenderContext<TFieldValues, TName>) => ReactElement;\n /** `false`: render the control as is, for one that wires its own ids from the\n * context. Default `true`. */\n asControl?: boolean;\n /** `false`: no {@link FormMessage}, for a control that renders its own error (its\n * `error` prop). Default `true`. */\n message?: boolean;\n /** `false`: no {@link FormLabel}, for a control that carries its label itself (a\n * checkbox). Default `true`. */\n showLabel?: boolean;\n}\n\nfunction hasContent(node: ReactNode): boolean {\n return node !== undefined && node !== null && node !== false && node !== \"\";\n}\n\n/** The label, with an id the control can be named by. Inside the item, so it can read\n * the item's id. */\nfunction RhfLabel({ required, children }: { required?: boolean; children: ReactNode }) {\n const { id } = useFormField();\n return (\n <FormLabel id={`${id}-label`} required={required}>\n {children}\n </FormLabel>\n );\n}\n\nfunction ControlSlot<TFieldValues extends FieldValues, TName extends FieldPath<TFieldValues>>({\n field,\n fieldState,\n render,\n asControl,\n}: {\n field: ControllerRenderProps<TFieldValues, TName>;\n fieldState: ControllerFieldState;\n render: RhfFieldProps<TFieldValues, TName>[\"render\"];\n asControl: boolean;\n}) {\n const { id, formItemId, describedBy } = useFormField();\n const element = render({\n field,\n fieldState,\n invalid: fieldState.invalid,\n error: fieldState.error?.message,\n id: formItemId,\n labelId: `${id}-label`,\n describedBy,\n });\n return asControl ? <FormControl>{element}</FormControl> : element;\n}\n\n/**\n * The shell every bound field is built on: label, control, hint and message around\n * a `render` of your own.\n *\n * ```tsx\n * <RhfField name=\"address\" label=\"Address\" render={({ field, invalid }) => (\n * <AddressAutocomplete value={field.value ?? \"\"} onChange={field.onChange} invalid={invalid} />\n * )} />\n * ```\n */\nexport function RhfField<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n render,\n asControl = true,\n message = true,\n showLabel = true,\n}: RhfFieldProps<TFieldValues, TName, TTransformed>) {\n return (\n <FormField\n control={control}\n name={name}\n rules={rules}\n disabled={excludeWhenDisabled ? disabled : undefined}\n render={({ field, fieldState }) => (\n <FormItem className={className}>\n {showLabel && hasContent(label) && <RhfLabel required={required}>{label}</RhfLabel>}\n <ControlSlot\n field={disabled && !field.disabled ? { ...field, disabled: true } : field}\n fieldState={fieldState}\n render={render}\n asControl={asControl}\n />\n {hasContent(hint) && <FormDescription>{hint}</FormDescription>}\n {message && <FormMessage />}\n </FormItem>\n )}\n />\n );\n}\n\n/**\n * Hands react-hook-form a focus handle for a control that forwards no ref: its\n * `shouldFocusError` calls `focus()` on whatever `field.ref` was given. `find` runs at\n * focus time, so it sees the element as it is then.\n */\nfunction useFocusHandle(ref: ControllerRenderProps[\"ref\"], find: () => HTMLElement | null | undefined) {\n const findRef = useRef(find);\n useLayoutEffect(() => {\n findRef.current = find;\n });\n useLayoutEffect(() => {\n ref({ focus: () => findRef.current()?.focus() });\n }, [ref]);\n}\n\n// ── text ─────────────────────────────────────────────────────────────────────\n\ntype OwnInputProps = Omit<\n InputProps,\n \"name\" | \"value\" | \"defaultValue\" | \"onChange\" | \"onBlur\" | \"ref\" | \"label\" | \"error\" | \"invalid\" | \"className\" | \"disabled\" | \"required\" | \"inputClassName\"\n> & {\n /**\n * Classes for the `<input>` — `className` is the item's box (kastlan 42: a\n * `font-mono` IBAN, a `tabular-nums` reference number). {@link RhfTextarea} and\n * {@link RhfNumberField} had it; this one only reached `Input`'s prop of the same\n * name by accident of the rest-spread, undocumented and one refactor from being\n * dropped. Declared, it is part of the contract the three share.\n */\n inputClassName?: string;\n};\n\nexport type RhfTextFieldProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> & OwnInputProps;\n\n/** A text {@link Input} — `type` for email, tel, password, url. Stores the string. */\nexport function RhfTextField<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n ...inputProps\n}: RhfTextFieldProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n render={({ field, invalid }) => (\n <Input\n aria-required={required || undefined}\n {...inputProps}\n name={field.name}\n ref={field.ref}\n value={(field.value ?? \"\") as string}\n onChange={field.onChange}\n onBlur={field.onBlur}\n disabled={field.disabled}\n invalid={invalid}\n />\n )}\n />\n );\n}\n\ntype OwnTextareaProps = Omit<\n TextareaProps,\n \"name\" | \"value\" | \"defaultValue\" | \"onChange\" | \"onBlur\" | \"ref\" | \"label\" | \"error\" | \"invalid\" | \"className\" | \"disabled\" | \"required\"\n> & {\n /** Classes for the `<textarea>`. */\n inputClassName?: string;\n};\n\nexport type RhfTextareaProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> & OwnTextareaProps;\n\n/** A multi-line {@link Textarea}; takes `rows`. Stores the string. */\nexport function RhfTextarea<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n inputClassName,\n ...areaProps\n}: RhfTextareaProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n render={({ field, invalid }) => (\n <Textarea\n aria-required={required || undefined}\n {...areaProps}\n className={inputClassName}\n name={field.name}\n ref={field.ref}\n value={(field.value ?? \"\") as string}\n onChange={field.onChange}\n onBlur={field.onBlur}\n disabled={field.disabled}\n invalid={invalid}\n />\n )}\n />\n );\n}\n\n// ── numbers ──────────────────────────────────────────────────────────────────\n\n/** A form value → the number field's `number | null`. Defaults hold `\"\"`, `null`, a\n * number, or a numeric string. */\nfunction toNumber(value: unknown): number | null {\n if (value === null || value === undefined || value === \"\") return null;\n const n = typeof value === \"number\" ? value : Number(String(value).replace(\",\", \".\"));\n return Number.isFinite(n) ? n : null;\n}\n\nexport type RhfNumberFieldProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> &\n Pick<\n NumberFieldProps,\n | \"digits\"\n | \"min\"\n | \"max\"\n | \"step\"\n | \"calculator\"\n | \"unit\"\n | \"unitPlacement\"\n | \"placeholder\"\n | \"inputClassName\"\n | \"locale\"\n | \"ariaLabel\"\n | \"autoFocus\"\n > & {\n /** What an emptied field stores. Default `null`; `\"\"` for a schema written\n * against a native number input (`z.coerce.number()` over `\"\"`). */\n emptyValue?: null | \"\";\n /** `false`: an emptied field snaps back to its last number instead of storing\n * `emptyValue`. Default `true`. */\n nullable?: boolean;\n };\n\n/**\n * The kit's {@link NumberField}: a parsed, rounded (`digits`) and clamped (`min` /\n * `max`) number, committed on blur or Enter in the locale's decimal mark. Stores a\n * number, or `emptyValue` when emptied.\n */\nexport function RhfNumberField<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n emptyValue = null,\n nullable = true,\n ...numberProps\n}: RhfNumberFieldProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n render={({ field, invalid, id }) => (\n // FormControl clones this element with `id` / `aria-describedby` /\n // `aria-invalid`, which NumberControl hands on to the field.\n <NumberControl\n field={field as unknown as ControllerRenderProps}\n invalid={invalid}\n required={required}\n id={id}\n emptyValue={emptyValue}\n nullable={nullable}\n numberProps={numberProps}\n />\n )}\n />\n );\n}\n\nfunction NumberControl({\n field,\n invalid,\n required,\n id,\n emptyValue,\n nullable,\n numberProps,\n ...aria\n}: {\n field: ControllerRenderProps;\n invalid: boolean;\n required?: boolean;\n id: string;\n emptyValue: null | \"\";\n nullable: boolean;\n numberProps: Omit<RhfNumberFieldProps, keyof RhfFieldBaseProps | \"emptyValue\" | \"nullable\">;\n \"aria-describedby\"?: string;\n \"aria-invalid\"?: NumberFieldProps[\"aria-invalid\"];\n}) {\n // NumberField forwards no ref; it routes `id` to its <input>, where the handle\n // finds it.\n useFocusHandle(field.ref, () => document.getElementById(id));\n return (\n <NumberField\n {...numberProps}\n aria-describedby={aria[\"aria-describedby\"]}\n aria-invalid={aria[\"aria-invalid\"]}\n aria-required={required || undefined}\n id={id}\n value={toNumber(field.value)}\n onCommit={(n) => {\n field.onChange(n ?? emptyValue);\n field.onBlur();\n }}\n nullable={nullable}\n disabled={field.disabled}\n invalid={invalid}\n />\n );\n}\n\nexport type RhfIntegerFieldProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfNumberFieldProps<TFieldValues, TName, TTransformed>;\n\n/**\n * {@link RhfNumberField} for a whole number — a floor, a room count, a year, a\n * notice period in months. Every such call site in kastlan (item 41) spelled out the\n * same three props, `digits={0} calculator={false} emptyValue=\"\"`, and a preset\n * written thirty times is one that is eventually written wrong once:\n *\n * - `digits={0}`: rounds on commit, so \"2.5\" rooms settles to 3 instead of reaching\n * an `Integer` column and failing server-side;\n * - `calculator={false}`: a count is typed, not worked out — the trigger is noise\n * beside a two-digit field;\n * - `emptyValue=\"\"`: kastlan's integer schemas are `z.coerce.number()` over `\"\"`,\n * written against the native number inputs these fields replaced.\n *\n * Each is only a default: pass the prop to override it (`emptyValue={null}` for a\n * nullable column). Everything else is {@link RhfNumberField}'s.\n */\nexport function RhfIntegerField<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>(props: RhfIntegerFieldProps<TFieldValues, TName, TTransformed>) {\n // `??` / `=== undefined` rather than a spread over the defaults, so a caller\n // forwarding its own optional prop (`digits={props.digits}`) still gets the preset,\n // while an explicit `emptyValue={null}` keeps its null.\n return (\n <RhfNumberField\n {...props}\n digits={props.digits ?? 0}\n calculator={props.calculator ?? false}\n emptyValue={props.emptyValue === undefined ? \"\" : props.emptyValue}\n />\n );\n}\n\n// ── money ────────────────────────────────────────────────────────────────────\n\nexport type RhfMoneyFieldProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> & {\n placeholder?: string;\n /** The currency chip's code (\"CHF\"). */\n currency?: string;\n /** Makes the chip a currency picker. Bind it to another field with\n * `useController`, or to state. */\n onCurrencyChange?: (code: string) => void;\n /** Colours the figure for the direction of money. */\n tone?: \"neutral\" | \"outflow\" | \"inflow\";\n align?: \"start\" | \"center\";\n ariaLabel?: string;\n autoFocus?: boolean;\n /**\n * What the form stores: `\"number\"` (default) — `12.5`, or `emptyValue` while the\n * field is empty — or `\"string\"`, the field's own text (\"12.50\") for a schema that\n * parses it itself. A half-typed sum (\"12+\") leaves the stored number as it was\n * until it resolves.\n */\n valueAs?: \"number\" | \"string\";\n /** What an emptied field stores when `valueAs` is `\"number\"`. Default `null`. */\n emptyValue?: null | \"\";\n /** Decimals the amount settles to on blur, Enter or a calculator result. Default:\n * the currency's minor unit (CHF 2, JPY 0). See {@link AmountInput}'s `digits`. */\n digits?: number;\n /** Clamp the settled amount (a release capped at the deposit's balance). Validate\n * with `rules` as well if a clamp needs explaining. */\n min?: number;\n max?: number;\n};\n\n/** The amount a text reads as, or `undefined` for a draft that is not one yet. */\nfunction parseAmount(text: string): number | null | undefined {\n const trimmed = text.trim();\n if (trimmed === \"\") return null;\n if (!/^-?\\d*[.,]?\\d*$/.test(trimmed)) return undefined;\n const n = Number(trimmed.replace(\",\", \".\"));\n return Number.isFinite(n) ? n : undefined;\n}\n\nfunction MoneyControl({\n field,\n invalid,\n required,\n id,\n describedBy,\n props,\n}: {\n field: ControllerRenderProps;\n invalid: boolean;\n required?: boolean;\n id: string;\n describedBy: string | undefined;\n props: Omit<RhfMoneyFieldProps, keyof RhfFieldBaseProps>;\n}) {\n const { valueAs = \"number\", emptyValue = null, ariaLabel, ...amountProps } = props;\n const value: unknown = field.value;\n const external = value === null || value === undefined ? \"\" : String(value);\n // The text being typed. A stored NUMBER cannot hold \"12.\" or \"12+5\", so the draft\n // lives here and is re-read from the form only when the form's value moves away\n // from what the draft already says (a reset, a setValue).\n const [draft, setDraft] = useState(external);\n const [seen, setSeen] = useState<unknown>(value);\n if (seen !== value) {\n setSeen(value);\n const current = valueAs === \"string\" ? draft : parseAmount(draft);\n const same = valueAs === \"string\" ? current === external : current === toNumber(value);\n if (!same) setDraft(external);\n }\n const input = useRef<HTMLInputElement | null>(null);\n // AmountInput reports no blur, and react-hook-form needs one to mark the field\n // touched: listen on its <input>.\n const onBlur = field.onBlur;\n useLayoutEffect(() => {\n const el = input.current;\n if (!el) return;\n el.addEventListener(\"blur\", onBlur);\n return () => el.removeEventListener(\"blur\", onBlur);\n }, [onBlur]);\n return (\n <div>\n <AmountInput\n {...amountProps}\n ariaLabel={ariaLabel}\n id={id}\n aria-describedby={describedBy}\n aria-required={required || undefined}\n ref={(el) => {\n input.current = el;\n field.ref(el);\n }}\n value={draft}\n disabled={field.disabled}\n invalid={invalid}\n onChange={(text) => {\n setDraft(text);\n if (valueAs === \"string\") {\n field.onChange(text);\n return;\n }\n const parsed = parseAmount(text);\n if (parsed === undefined) return;\n field.onChange(parsed ?? emptyValue);\n }}\n />\n </div>\n );\n}\n\n/**\n * The kit's {@link AmountInput}: a money figure with its currency chip and the\n * calculator (\"1200+80\" resolves on blur or Enter). Stores a number by default — see\n * `valueAs`.\n */\nexport function RhfMoneyField<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n ...amountProps\n}: RhfMoneyFieldProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n asControl={false}\n render={({ field, invalid, id, describedBy }) => (\n <MoneyControl\n field={field as unknown as ControllerRenderProps}\n invalid={invalid}\n required={required}\n id={id}\n describedBy={describedBy}\n props={amountProps}\n />\n )}\n />\n );\n}\n\n// ── date ─────────────────────────────────────────────────────────────────────\n\nexport type RhfDateFieldProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> &\n Omit<DatePickerProps, \"value\" | \"onChange\" | \"label\" | \"invalid\" | \"disabled\" | \"className\" | \"id\"> & {\n /** Classes for the picker. Default `w-full`. */\n inputClassName?: string;\n /** What a cleared date stores. Default `\"\"`, the empty ISO string; `null` for a\n * nullable schema. */\n emptyValue?: \"\" | null;\n };\n\nfunction DateControl({\n field,\n invalid,\n required,\n id,\n emptyValue,\n inputClassName,\n pickerProps,\n ...aria\n}: {\n field: ControllerRenderProps;\n invalid: boolean;\n required?: boolean;\n id: string;\n emptyValue: \"\" | null;\n inputClassName?: string;\n pickerProps: Omit<DatePickerProps, \"value\" | \"onChange\" | \"label\" | \"invalid\" | \"disabled\" | \"className\" | \"id\">;\n \"aria-describedby\"?: string;\n \"aria-invalid\"?: DatePickerProps[\"aria-invalid\"];\n}) {\n useFocusHandle(field.ref, () => document.getElementById(id));\n const value: unknown = field.value;\n return (\n <DatePicker\n {...pickerProps}\n {...aria}\n aria-required={required || undefined}\n id={id}\n value={typeof value === \"string\" ? value : \"\"}\n onChange={(iso) => {\n field.onChange(iso === \"\" ? emptyValue : iso);\n field.onBlur();\n }}\n disabled={field.disabled}\n invalid={invalid}\n className={inputClassName ?? \"w-full\"}\n />\n );\n}\n\n/** The kit's {@link DatePicker}, holding an ISO `\"YYYY-MM-DD\"` string. */\nexport function RhfDateField<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n inputClassName,\n emptyValue = \"\",\n ...pickerProps\n}: RhfDateFieldProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n render={({ field, invalid, id }) => (\n // FormControl clones this element with `aria-describedby` / `aria-invalid`,\n // which DateControl hands on to the picker's trigger.\n <DateControl\n field={field as unknown as ControllerRenderProps}\n invalid={invalid}\n required={required}\n id={id}\n emptyValue={emptyValue}\n inputClassName={inputClassName}\n pickerProps={pickerProps}\n />\n )}\n />\n );\n}\n\n// ── select ───────────────────────────────────────────────────────────────────\n\nexport interface RhfSelectOption {\n value: string | number;\n label: ReactNode;\n disabled?: boolean;\n}\n\nexport type RhfSelectProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> &\n Pick<SelectProps, \"size\" | \"autoFocus\" | \"aria-label\"> & {\n /** The options, as data. Or pass `<option>` children. */\n options?: readonly RhfSelectOption[];\n children?: ReactNode;\n /** A first, empty option (\"Choose…\"), selected while the value is empty. */\n placeholder?: string;\n /** Store `Number(value)` rather than the option's string. An empty choice still\n * stores `\"\"`. */\n valueAsNumber?: boolean;\n /** Classes for the select. Default `w-full`. */\n selectClassName?: string;\n };\n\n/** A native {@link Select}, from `options` or `<option>` children. */\nexport function RhfSelect<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n options,\n children,\n placeholder,\n valueAsNumber,\n selectClassName,\n ...selectProps\n}: RhfSelectProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n render={({ field, invalid }) => (\n <Select\n aria-required={required || undefined}\n {...selectProps}\n className={cn(\"w-full\", selectClassName)}\n name={field.name}\n ref={field.ref}\n value={(field.value ?? \"\") as string | number}\n onChange={(e) => {\n const raw = e.target.value;\n field.onChange(valueAsNumber && raw !== \"\" ? Number(raw) : raw);\n }}\n onBlur={field.onBlur}\n disabled={field.disabled}\n invalid={invalid}\n >\n {placeholder !== undefined && <option value=\"\">{placeholder}</option>}\n {options\n ? options.map((o) => (\n <option key={String(o.value)} value={o.value} disabled={o.disabled}>\n {o.label}\n </option>\n ))\n : children}\n </Select>\n )}\n />\n );\n}\n\n// ── checkbox ─────────────────────────────────────────────────────────────────\n\nexport type RhfCheckboxProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> &\n Pick<CheckboxProps, \"inputClassName\" | \"autoFocus\" | \"aria-label\">;\n\n/**\n * The kit's {@link Checkbox}, label beside the box and `hint` under it (the\n * checkbox's own `description`). Stores a boolean. `required` is the native one here\n * — see Checkbox — so a `<form>` refuses to submit it unticked.\n */\nexport function RhfCheckbox<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n ...boxProps\n}: RhfCheckboxProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, required, disabled, excludeWhenDisabled, className }}\n showLabel={false}\n render={({ field, invalid }) => (\n <Checkbox\n {...boxProps}\n ref={field.ref}\n name={field.name}\n checked={Boolean(field.value)}\n onCheckedChange={field.onChange}\n onBlur={field.onBlur}\n disabled={field.disabled}\n required={required}\n invalid={invalid}\n label={label}\n description={hint}\n />\n )}\n />\n );\n}\n\n// ── comboboxes ───────────────────────────────────────────────────────────────\n\nexport type RhfComboboxProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n V extends string | number = string | number,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> &\n Pick<\n EntityComboboxProps<V>,\n | \"options\"\n | \"loadOptions\"\n | \"loading\"\n | \"placeholder\"\n | \"searchPlaceholder\"\n | \"emptyLabel\"\n | \"clearable\"\n | \"clearLabel\"\n | \"onCreate\"\n | \"createLabel\"\n | \"filter\"\n | \"minChars\"\n | \"debounceMs\"\n > & {\n /** What a clear stores — the picker's `clearValue`. Default `null`; `\"\"` for a\n * schema that spells \"no choice\" as an empty string. */\n clearValue?: ComboClearValue;\n /** Classes for the picker. */\n comboClassName?: string;\n };\n\nfunction EntityControl<V extends string | number>({\n field,\n invalid,\n required,\n error,\n id,\n describedBy,\n clearValue,\n comboClassName,\n comboProps,\n}: {\n field: ControllerRenderProps;\n invalid: boolean;\n required?: boolean;\n error: string | undefined;\n id: string;\n describedBy: string | undefined;\n clearValue: ComboClearValue;\n comboClassName?: string;\n comboProps: Omit<RhfComboboxProps<FieldValues, string, V>, keyof RhfFieldBaseProps | \"clearValue\" | \"comboClassName\">;\n}) {\n const box = useRef<HTMLDivElement>(null);\n // EntityCombobox puts `id` and the ARIA below on its trigger, so the label's\n // `htmlFor` names it, the hint describes it and the focus handle finds it by id.\n useFocusHandle(field.ref, () => document.getElementById(id));\n // EntityCombobox reports no blur: focus leaving the picker marks the field touched.\n const onBlur = field.onBlur;\n useLayoutEffect(() => {\n const el = box.current;\n if (!el) return;\n el.addEventListener(\"focusout\", onBlur);\n return () => el.removeEventListener(\"focusout\", onBlur);\n }, [onBlur]);\n const value: unknown = field.value;\n return (\n <div ref={box}>\n <EntityCombobox<V, ComboClearValue>\n {...comboProps}\n className={comboClassName}\n id={id}\n aria-describedby={describedBy}\n aria-required={required || undefined}\n value={(value ?? null) as V | ComboClearValue | null}\n clearValue={clearValue}\n onChange={(v) => field.onChange(v)}\n disabled={field.disabled}\n invalid={invalid}\n // Its own message, which it merges into the trigger's aria-describedby after\n // the hint.\n error={error}\n />\n </div>\n );\n}\n\n/**\n * The kit's {@link EntityCombobox}: an id-keyed pick from `options` or `loadOptions`.\n * Stores the option's `value`, or `clearValue` on a clear (only offered with\n * `clearable`).\n */\nexport function RhfCombobox<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n V extends string | number = string | number,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n clearValue = null,\n comboClassName,\n ...comboProps\n}: RhfComboboxProps<TFieldValues, TName, V, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n asControl={false}\n message={false}\n render={({ field, invalid, error, id, describedBy }) => (\n <EntityControl<V>\n field={field as unknown as ControllerRenderProps}\n invalid={invalid}\n required={required}\n error={error}\n id={id}\n describedBy={describedBy}\n clearValue={clearValue}\n comboClassName={comboClassName}\n comboProps={comboProps}\n />\n )}\n />\n );\n}\n\nexport type RhfTextComboboxProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> &\n Pick<\n ComboboxProps,\n | \"options\"\n | \"placeholder\"\n | \"groupBy\"\n | \"maxSuggestions\"\n | \"searchPlaceholder\"\n | \"createLabel\"\n | \"optionAdornment\"\n | \"autoFocus\"\n | \"aria-label\"\n > & {\n /** Classes for the combobox. */\n comboClassName?: string;\n };\n\n/**\n * The kit's free-text {@link Combobox}: type anything, or pick one of `options`.\n * Stores the string.\n */\nexport function RhfTextCombobox<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n comboClassName,\n ...comboProps\n}: RhfTextComboboxProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n asControl={false}\n message={false}\n render={({ field, invalid, error, id, describedBy }) => (\n <TextComboControl\n field={field as unknown as ControllerRenderProps}\n invalid={invalid}\n required={required}\n error={error}\n id={id}\n describedBy={describedBy}\n className={comboClassName}\n comboProps={comboProps}\n />\n )}\n />\n );\n}\n\nfunction TextComboControl({\n field,\n invalid,\n required,\n error,\n id,\n describedBy,\n className,\n comboProps,\n}: {\n field: ControllerRenderProps;\n invalid: boolean;\n required?: boolean;\n error: string | undefined;\n id: string;\n describedBy: string | undefined;\n className?: string;\n comboProps: Omit<RhfTextComboboxProps, keyof RhfFieldBaseProps | \"comboClassName\">;\n}) {\n // The combobox routes `id` and its ARIA to its <input>, so the label's `htmlFor`\n // names it, the hint describes it and the focus handle finds it; the error is its\n // own `error` prop, which it merges in after the hint.\n useFocusHandle(field.ref, () => document.getElementById(id));\n const value: unknown = field.value;\n return (\n <Combobox\n {...comboProps}\n id={id}\n aria-describedby={describedBy}\n aria-required={required || undefined}\n className={className}\n value={typeof value === \"string\" ? value : value == null ? \"\" : String(value)}\n onChange={field.onChange}\n onBlur={field.onBlur}\n disabled={field.disabled}\n invalid={invalid}\n error={error}\n />\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/rhf/fields.tsx"],"sourcesContent":["/**\n * Bound fields: one line per field of a react-hook-form form. `@eifi1/ui-kit/rhf`.\n *\n * ```tsx\n * <Form {...form}>\n * <RhfTextField name=\"name\" label=\"Name\" hint=\"As on the lease\" required\n * rules={{ required: \"Enter a name\" }} />\n * <RhfMoneyField name=\"rent\" label=\"Net rent\" currency=\"CHF\" />\n * <RhfDateField name=\"start\" label=\"Start\" />\n * <RhfSelect name=\"type\" label=\"Type\" options={TYPES} />\n * <RhfCombobox name=\"tenantId\" label=\"Tenant\" options={tenants} clearable />\n * <RhfCheckbox name=\"isDefault\" label=\"Default account\" />\n * </Form>\n * ```\n *\n * Each folds the `FormField → FormItem → FormLabel → FormControl → field →\n * FormDescription → FormMessage` scaffold (see ./form) into one element, the way\n * kastlan's shared/components/form/fields.tsx does for its forms — with what that file\n * left out:\n *\n * - **The red border.** Every field gets `invalid` from the field state, so an errored\n * field PAINTS as well as announces. kastlan's number, money, date and entity fields\n * passed only `aria-invalid` through `FormControl`, or nothing, and `Input`, `Select`\n * and `Textarea` paint only from the prop (see the note in ./form).\n * - **Focus on error.** `field.ref` reaches the focusable element — the element itself\n * where the kit field forwards a ref, a focus handle on it where it does not (the\n * number field, the pickers) — so `handleSubmit` and `trigger(…, { shouldFocus })`\n * land the caret on the first field in error.\n * - **`control` is optional**: under `<Form {...form}>` the fields find the form\n * through react-hook-form's context. Pass it for the field's value types\n * (`control={form.control}` checks `name` against the form's values).\n *\n * The common props: `name`, `control`, `label` (a {@link FormLabel} above the field;\n * omitted, none — then give the field an `aria-label`), `hint` (standing advice under\n * the field, attached to it with `aria-describedby`), `required` (the label's mark,\n * and `aria-required` where the control takes it — validation is `rules`' or the\n * resolver's), `rules`, `disabled` (the control only — the value is still submitted;\n * `excludeWhenDisabled` for react-hook-form's drop-the-value semantics), and\n * `className` for the item's box.\n *\n * {@link RhfField} is the shell they are all built on, for a control the kit does not\n * ship (an address autocomplete): it takes a `render` and wires the rest.\n */\nimport { useLayoutEffect, useRef, useState, type ReactElement, type ReactNode } from \"react\";\nimport type {\n ControllerFieldState,\n ControllerProps,\n ControllerRenderProps,\n FieldPath,\n FieldValues,\n} from \"react-hook-form\";\nimport { FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, useFormField } from \"./form\";\nimport { Input, Select, Textarea, type InputProps, type SelectProps, type TextareaProps } from \"../components/ui\";\nimport { NumberField, type NumberFieldProps } from \"../components/number-field\";\nimport { AmountInput } from \"../components/amount-input\";\nimport { DatePicker, type DatePickerProps } from \"../components/date-picker\";\nimport { Checkbox, type CheckboxProps } from \"../components/checkbox\";\nimport { EntityCombobox, type EntityComboboxProps } from \"../components/entity-combobox\";\nimport { Combobox, type ComboboxProps } from \"../components/combobox\";\nimport type { ComboClearValue } from \"../components/combobox-core\";\nimport { cn } from \"../lib/cn\";\n\n// ── the shell ────────────────────────────────────────────────────────────────\n\n/** What every bound field takes. */\nexport interface RhfFieldBaseProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> {\n name: TName;\n /** `form.control`. Optional under `<Form {...form}>`; pass it to type-check `name`. */\n control?: ControllerProps<TFieldValues, TName, TTransformed>[\"control\"];\n /** react-hook-form's `rules` (`required`, `min`, `validate` …). */\n rules?: ControllerProps<TFieldValues, TName, TTransformed>[\"rules\"];\n /** A {@link FormLabel} above the field. Omitted: no label — name the control with\n * an `aria-label` instead. */\n label?: ReactNode;\n /** Standing advice under the field (\"As printed on the card\"), attached to the\n * control with `aria-describedby`. */\n hint?: ReactNode;\n /** Draws the label's required mark and sets `aria-required` where the control\n * takes it. Whether the field IS required is `rules`' or the resolver's to say. */\n required?: boolean;\n /** Disables the control and KEEPS the value: a field locked to a preset (a lease's\n * preselected unit, a fixed period) still submits it, and `rules` still run.\n * react-hook-form's own Controller `disabled` drops the value from `handleSubmit`'s\n * data instead, which a locked preset must never do (kastlan, 0.12). To get that,\n * add `excludeWhenDisabled`. A form-wide `useForm({ disabled })` still disables\n * every field the RHF way. */\n disabled?: boolean;\n /** With `disabled`: disable through react-hook-form, so the value is left out of\n * the submitted data and validation skips it, like a disabled native input in a\n * plain form post. Default `false`. */\n excludeWhenDisabled?: boolean;\n /** Classes for the item's box (a `grid gap-1`). */\n className?: string;\n}\n\n/** What {@link RhfField}'s `render` receives. */\nexport interface RhfFieldRenderContext<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n> {\n field: ControllerRenderProps<TFieldValues, TName>;\n fieldState: ControllerFieldState;\n /** The field has an error: pass it to the control's `invalid` so it paints. */\n invalid: boolean;\n /** The error's message, if any. */\n error: string | undefined;\n /** The control's id, which the label points at. `FormControl` sets it on the\n * rendered element already; this is for a control that routes it elsewhere. */\n id: string;\n /** The label's id, for a control that is named with `aria-labelledby`. */\n labelId: string;\n /** The ids of the rendered hint and message, if any. */\n describedBy: string | undefined;\n}\n\nexport interface RhfFieldProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> extends RhfFieldBaseProps<TFieldValues, TName, TTransformed> {\n /** The control. Wrapped in {@link FormControl} (its `id`, `aria-describedby` and\n * `aria-invalid`) unless `asControl` is false. */\n render: (ctx: RhfFieldRenderContext<TFieldValues, TName>) => ReactElement;\n /** `false`: render the control as is, for one that wires its own ids from the\n * context. Default `true`. */\n asControl?: boolean;\n /** `false`: no {@link FormMessage}, for a control that renders its own error (its\n * `error` prop). Default `true`. */\n message?: boolean;\n /** `false`: no {@link FormLabel}, for a control that carries its label itself (a\n * checkbox). Default `true`. */\n showLabel?: boolean;\n}\n\nfunction hasContent(node: ReactNode): boolean {\n return node !== undefined && node !== null && node !== false && node !== \"\";\n}\n\n/** The label, with an id the control can be named by. Inside the item, so it can read\n * the item's id. */\nfunction RhfLabel({ required, children }: { required?: boolean; children: ReactNode }) {\n const { id } = useFormField();\n return (\n <FormLabel id={`${id}-label`} required={required}>\n {children}\n </FormLabel>\n );\n}\n\nfunction ControlSlot<TFieldValues extends FieldValues, TName extends FieldPath<TFieldValues>>({\n field,\n fieldState,\n render,\n asControl,\n}: {\n field: ControllerRenderProps<TFieldValues, TName>;\n fieldState: ControllerFieldState;\n render: RhfFieldProps<TFieldValues, TName>[\"render\"];\n asControl: boolean;\n}) {\n const { id, formItemId, describedBy } = useFormField();\n const element = render({\n field,\n fieldState,\n invalid: fieldState.invalid,\n error: fieldState.error?.message,\n id: formItemId,\n labelId: `${id}-label`,\n describedBy,\n });\n return asControl ? <FormControl>{element}</FormControl> : element;\n}\n\n/**\n * The shell every bound field is built on: label, control, hint and message around\n * a `render` of your own.\n *\n * ```tsx\n * <RhfField name=\"address\" label=\"Address\" render={({ field, invalid }) => (\n * <AddressAutocomplete value={field.value ?? \"\"} onChange={field.onChange} invalid={invalid} />\n * )} />\n * ```\n */\nexport function RhfField<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n render,\n asControl = true,\n message = true,\n showLabel = true,\n}: RhfFieldProps<TFieldValues, TName, TTransformed>) {\n return (\n <FormField\n control={control}\n name={name}\n rules={rules}\n disabled={excludeWhenDisabled ? disabled : undefined}\n render={({ field, fieldState }) => (\n <FormItem className={className}>\n {showLabel && hasContent(label) && <RhfLabel required={required}>{label}</RhfLabel>}\n <ControlSlot\n field={disabled && !field.disabled ? { ...field, disabled: true } : field}\n fieldState={fieldState}\n render={render}\n asControl={asControl}\n />\n {hasContent(hint) && <FormDescription>{hint}</FormDescription>}\n {message && <FormMessage />}\n </FormItem>\n )}\n />\n );\n}\n\n/**\n * Hands react-hook-form a focus handle for a control that forwards no ref: its\n * `shouldFocusError` calls `focus()` on whatever `field.ref` was given. `find` runs at\n * focus time, so it sees the element as it is then.\n */\nfunction useFocusHandle(ref: ControllerRenderProps[\"ref\"], find: () => HTMLElement | null | undefined) {\n const findRef = useRef(find);\n useLayoutEffect(() => {\n findRef.current = find;\n });\n useLayoutEffect(() => {\n ref({ focus: () => findRef.current()?.focus() });\n }, [ref]);\n}\n\n// ── text ─────────────────────────────────────────────────────────────────────\n\ntype OwnInputProps = Omit<\n InputProps,\n \"name\" | \"value\" | \"defaultValue\" | \"onChange\" | \"onBlur\" | \"ref\" | \"label\" | \"error\" | \"invalid\" | \"className\" | \"disabled\" | \"required\" | \"inputClassName\"\n> & {\n /**\n * Classes for the `<input>` — `className` is the item's box (kastlan 42: a\n * `font-mono` IBAN, a `tabular-nums` reference number). {@link RhfTextarea} and\n * {@link RhfNumberField} had it; this one only reached `Input`'s prop of the same\n * name by accident of the rest-spread, undocumented and one refactor from being\n * dropped. Declared, it is part of the contract the three share.\n */\n inputClassName?: string;\n};\n\nexport type RhfTextFieldProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> & OwnInputProps;\n\n/** A text {@link Input} — `type` for email, tel, password, url. Stores the string. */\nexport function RhfTextField<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n ...inputProps\n}: RhfTextFieldProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n render={({ field, invalid }) => (\n <Input\n aria-required={required || undefined}\n {...inputProps}\n name={field.name}\n ref={field.ref}\n value={(field.value ?? \"\") as string}\n onChange={field.onChange}\n onBlur={field.onBlur}\n disabled={field.disabled}\n invalid={invalid}\n />\n )}\n />\n );\n}\n\ntype OwnTextareaProps = Omit<\n TextareaProps,\n \"name\" | \"value\" | \"defaultValue\" | \"onChange\" | \"onBlur\" | \"ref\" | \"label\" | \"error\" | \"invalid\" | \"className\" | \"disabled\" | \"required\"\n> & {\n /** Classes for the `<textarea>`. */\n inputClassName?: string;\n};\n\nexport type RhfTextareaProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> & OwnTextareaProps;\n\n/** A multi-line {@link Textarea}; takes `rows`. Stores the string. */\nexport function RhfTextarea<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n inputClassName,\n ...areaProps\n}: RhfTextareaProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n render={({ field, invalid }) => (\n <Textarea\n aria-required={required || undefined}\n {...areaProps}\n className={inputClassName}\n name={field.name}\n ref={field.ref}\n value={(field.value ?? \"\") as string}\n onChange={field.onChange}\n onBlur={field.onBlur}\n disabled={field.disabled}\n invalid={invalid}\n />\n )}\n />\n );\n}\n\n// ── numbers ──────────────────────────────────────────────────────────────────\n\n/** A form value → the number field's `number | null`. Defaults hold `\"\"`, `null`, a\n * number, or a numeric string. */\nfunction toNumber(value: unknown): number | null {\n if (value === null || value === undefined || value === \"\") return null;\n const n = typeof value === \"number\" ? value : Number(String(value).replace(\",\", \".\"));\n return Number.isFinite(n) ? n : null;\n}\n\nexport type RhfNumberFieldProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> &\n Pick<\n NumberFieldProps,\n | \"digits\"\n | \"min\"\n | \"max\"\n | \"step\"\n | \"calculator\"\n | \"unit\"\n | \"unitPlacement\"\n | \"placeholder\"\n | \"inputClassName\"\n | \"locale\"\n | \"ariaLabel\"\n | \"autoFocus\"\n > & {\n /** What an emptied field stores. Default `null`; `\"\"` for a schema written\n * against a native number input (`z.coerce.number()` over `\"\"`). */\n emptyValue?: null | \"\";\n /** `false`: an emptied field snaps back to its last number instead of storing\n * `emptyValue`. Default `true`. */\n nullable?: boolean;\n };\n\n/**\n * The kit's {@link NumberField}: a parsed, rounded (`digits`) and clamped (`min` /\n * `max`) number, committed on blur or Enter in the locale's decimal mark. Stores a\n * number, or `emptyValue` when emptied.\n */\nexport function RhfNumberField<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n emptyValue = null,\n nullable = true,\n ...numberProps\n}: RhfNumberFieldProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n render={({ field, invalid, id }) => (\n // FormControl clones this element with `id` / `aria-describedby` /\n // `aria-invalid`, which NumberControl hands on to the field.\n <NumberControl\n field={field as unknown as ControllerRenderProps}\n invalid={invalid}\n required={required}\n id={id}\n emptyValue={emptyValue}\n nullable={nullable}\n numberProps={numberProps}\n />\n )}\n />\n );\n}\n\nfunction NumberControl({\n field,\n invalid,\n required,\n id,\n emptyValue,\n nullable,\n numberProps,\n ...aria\n}: {\n field: ControllerRenderProps;\n invalid: boolean;\n required?: boolean;\n id: string;\n emptyValue: null | \"\";\n nullable: boolean;\n numberProps: Omit<RhfNumberFieldProps, keyof RhfFieldBaseProps | \"emptyValue\" | \"nullable\">;\n \"aria-describedby\"?: string;\n \"aria-invalid\"?: NumberFieldProps[\"aria-invalid\"];\n}) {\n // NumberField forwards no ref; it routes `id` to its <input>, where the handle\n // finds it.\n useFocusHandle(field.ref, () => document.getElementById(id));\n return (\n <NumberField\n {...numberProps}\n aria-describedby={aria[\"aria-describedby\"]}\n aria-invalid={aria[\"aria-invalid\"]}\n aria-required={required || undefined}\n id={id}\n value={toNumber(field.value)}\n onCommit={(n) => {\n field.onChange(n ?? emptyValue);\n field.onBlur();\n }}\n nullable={nullable}\n disabled={field.disabled}\n invalid={invalid}\n />\n );\n}\n\nexport type RhfIntegerFieldProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfNumberFieldProps<TFieldValues, TName, TTransformed>;\n\n/**\n * {@link RhfNumberField} for a whole number — a floor, a room count, a year, a\n * notice period in months. Every such call site in kastlan (item 41) spelled out the\n * same three props, `digits={0} calculator={false} emptyValue=\"\"`, and a preset\n * written thirty times is one that is eventually written wrong once:\n *\n * - `digits={0}`: rounds on commit, so \"2.5\" rooms settles to 3 instead of reaching\n * an `Integer` column and failing server-side;\n * - `calculator={false}`: a count is typed, not worked out — the trigger is noise\n * beside a two-digit field;\n * - `emptyValue=\"\"`: kastlan's integer schemas are `z.coerce.number()` over `\"\"`,\n * written against the native number inputs these fields replaced.\n *\n * Each is only a default: pass the prop to override it (`emptyValue={null}` for a\n * nullable column). Everything else is {@link RhfNumberField}'s.\n */\nexport function RhfIntegerField<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>(props: RhfIntegerFieldProps<TFieldValues, TName, TTransformed>) {\n // `??` / `=== undefined` rather than a spread over the defaults, so a caller\n // forwarding its own optional prop (`digits={props.digits}`) still gets the preset,\n // while an explicit `emptyValue={null}` keeps its null.\n return (\n <RhfNumberField\n {...props}\n digits={props.digits ?? 0}\n calculator={props.calculator ?? false}\n emptyValue={props.emptyValue === undefined ? \"\" : props.emptyValue}\n />\n );\n}\n\n// ── money ────────────────────────────────────────────────────────────────────\n\nexport type RhfMoneyFieldProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> & {\n placeholder?: string;\n /** The currency chip's code (\"CHF\"). */\n currency?: string;\n /** Makes the chip a currency picker. Bind it to another field with\n * `useController`, or to state. */\n onCurrencyChange?: (code: string) => void;\n /** Colours the figure for the direction of money. */\n tone?: \"neutral\" | \"outflow\" | \"inflow\";\n align?: \"start\" | \"center\";\n ariaLabel?: string;\n autoFocus?: boolean;\n /**\n * What the form stores: `\"number\"` (default) — `12.5`, or `emptyValue` while the\n * field is empty — or `\"string\"`, the field's own text (\"12.50\") for a schema that\n * parses it itself. A half-typed sum (\"12+\") leaves the stored number as it was\n * until it resolves.\n */\n valueAs?: \"number\" | \"string\";\n /** What an emptied field stores when `valueAs` is `\"number\"`. Default `null`. */\n emptyValue?: null | \"\";\n /** Decimals the amount settles to on blur, Enter or a calculator result. Default:\n * the currency's minor unit (CHF 2, JPY 0). ⚠️ A unit price or a rate needs its\n * column's scale here (`digits={4}` for 1.789 €/l), or it is stored rounded to\n * cents without a word (keksdose G2). See {@link AmountInput}'s `digits`. */\n digits?: number;\n /** Clamp the settled amount (a release capped at the deposit's balance). Validate\n * with `rules` as well if a clamp needs explaining. */\n min?: number;\n max?: number;\n};\n\n/** The amount a text reads as, or `undefined` for a draft that is not one yet. */\nfunction parseAmount(text: string): number | null | undefined {\n const trimmed = text.trim();\n if (trimmed === \"\") return null;\n if (!/^-?\\d*[.,]?\\d*$/.test(trimmed)) return undefined;\n const n = Number(trimmed.replace(\",\", \".\"));\n return Number.isFinite(n) ? n : undefined;\n}\n\nfunction MoneyControl({\n field,\n invalid,\n required,\n id,\n describedBy,\n props,\n}: {\n field: ControllerRenderProps;\n invalid: boolean;\n required?: boolean;\n id: string;\n describedBy: string | undefined;\n props: Omit<RhfMoneyFieldProps, keyof RhfFieldBaseProps>;\n}) {\n const { valueAs = \"number\", emptyValue = null, ariaLabel, ...amountProps } = props;\n const value: unknown = field.value;\n const external = value === null || value === undefined ? \"\" : String(value);\n // The text being typed. A stored NUMBER cannot hold \"12.\" or \"12+5\", so the draft\n // lives here and is re-read from the form only when the form's value moves away\n // from what the draft already says (a reset, a setValue).\n const [draft, setDraft] = useState(external);\n const [seen, setSeen] = useState<unknown>(value);\n if (seen !== value) {\n setSeen(value);\n const current = valueAs === \"string\" ? draft : parseAmount(draft);\n const same = valueAs === \"string\" ? current === external : current === toNumber(value);\n if (!same) setDraft(external);\n }\n const input = useRef<HTMLInputElement | null>(null);\n // AmountInput reports no blur, and react-hook-form needs one to mark the field\n // touched: listen on its <input>.\n const onBlur = field.onBlur;\n useLayoutEffect(() => {\n const el = input.current;\n if (!el) return;\n el.addEventListener(\"blur\", onBlur);\n return () => el.removeEventListener(\"blur\", onBlur);\n }, [onBlur]);\n return (\n <div>\n <AmountInput\n {...amountProps}\n ariaLabel={ariaLabel}\n id={id}\n aria-describedby={describedBy}\n aria-required={required || undefined}\n ref={(el) => {\n input.current = el;\n field.ref(el);\n }}\n value={draft}\n disabled={field.disabled}\n invalid={invalid}\n onChange={(text) => {\n setDraft(text);\n if (valueAs === \"string\") {\n field.onChange(text);\n return;\n }\n const parsed = parseAmount(text);\n if (parsed === undefined) return;\n field.onChange(parsed ?? emptyValue);\n }}\n />\n </div>\n );\n}\n\n/**\n * The kit's {@link AmountInput}: a money figure with its currency chip and the\n * calculator (\"1200+80\" resolves on blur or Enter). Stores a number by default — see\n * `valueAs`.\n */\nexport function RhfMoneyField<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n ...amountProps\n}: RhfMoneyFieldProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n asControl={false}\n render={({ field, invalid, id, describedBy }) => (\n <MoneyControl\n field={field as unknown as ControllerRenderProps}\n invalid={invalid}\n required={required}\n id={id}\n describedBy={describedBy}\n props={amountProps}\n />\n )}\n />\n );\n}\n\n// ── date ─────────────────────────────────────────────────────────────────────\n\nexport type RhfDateFieldProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> &\n Omit<DatePickerProps, \"value\" | \"onChange\" | \"label\" | \"invalid\" | \"disabled\" | \"className\" | \"id\"> & {\n /** Classes for the picker. Default `w-full`. */\n inputClassName?: string;\n /** What a cleared date stores. Default `\"\"`, the empty ISO string; `null` for a\n * nullable schema. */\n emptyValue?: \"\" | null;\n };\n\nfunction DateControl({\n field,\n invalid,\n required,\n id,\n emptyValue,\n inputClassName,\n pickerProps,\n ...aria\n}: {\n field: ControllerRenderProps;\n invalid: boolean;\n required?: boolean;\n id: string;\n emptyValue: \"\" | null;\n inputClassName?: string;\n pickerProps: Omit<DatePickerProps, \"value\" | \"onChange\" | \"label\" | \"invalid\" | \"disabled\" | \"className\" | \"id\">;\n \"aria-describedby\"?: string;\n \"aria-invalid\"?: DatePickerProps[\"aria-invalid\"];\n}) {\n useFocusHandle(field.ref, () => document.getElementById(id));\n const value: unknown = field.value;\n return (\n <DatePicker\n {...pickerProps}\n {...aria}\n aria-required={required || undefined}\n id={id}\n value={typeof value === \"string\" ? value : \"\"}\n onChange={(iso) => {\n field.onChange(iso === \"\" ? emptyValue : iso);\n field.onBlur();\n }}\n disabled={field.disabled}\n invalid={invalid}\n className={inputClassName ?? \"w-full\"}\n />\n );\n}\n\n/** The kit's {@link DatePicker}, holding an ISO `\"YYYY-MM-DD\"` string. */\nexport function RhfDateField<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n inputClassName,\n emptyValue = \"\",\n ...pickerProps\n}: RhfDateFieldProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n render={({ field, invalid, id }) => (\n // FormControl clones this element with `aria-describedby` / `aria-invalid`,\n // which DateControl hands on to the picker's trigger.\n <DateControl\n field={field as unknown as ControllerRenderProps}\n invalid={invalid}\n required={required}\n id={id}\n emptyValue={emptyValue}\n inputClassName={inputClassName}\n pickerProps={pickerProps}\n />\n )}\n />\n );\n}\n\n// ── select ───────────────────────────────────────────────────────────────────\n\nexport interface RhfSelectOption {\n value: string | number;\n label: ReactNode;\n disabled?: boolean;\n}\n\nexport type RhfSelectProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> &\n Pick<SelectProps, \"size\" | \"autoFocus\" | \"aria-label\"> & {\n /** The options, as data. Or pass `<option>` children. */\n options?: readonly RhfSelectOption[];\n children?: ReactNode;\n /** A first, empty option (\"Choose…\"), selected while the value is empty. */\n placeholder?: string;\n /** Store `Number(value)` rather than the option's string. An empty choice still\n * stores `\"\"`. */\n valueAsNumber?: boolean;\n /** Classes for the select. Default `w-full`. */\n selectClassName?: string;\n };\n\n/** A native {@link Select}, from `options` or `<option>` children. */\nexport function RhfSelect<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n options,\n children,\n placeholder,\n valueAsNumber,\n selectClassName,\n ...selectProps\n}: RhfSelectProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n render={({ field, invalid }) => (\n <Select\n aria-required={required || undefined}\n {...selectProps}\n className={cn(\"w-full\", selectClassName)}\n name={field.name}\n ref={field.ref}\n value={(field.value ?? \"\") as string | number}\n onChange={(e) => {\n const raw = e.target.value;\n field.onChange(valueAsNumber && raw !== \"\" ? Number(raw) : raw);\n }}\n onBlur={field.onBlur}\n disabled={field.disabled}\n invalid={invalid}\n >\n {placeholder !== undefined && <option value=\"\">{placeholder}</option>}\n {options\n ? options.map((o) => (\n <option key={String(o.value)} value={o.value} disabled={o.disabled}>\n {o.label}\n </option>\n ))\n : children}\n </Select>\n )}\n />\n );\n}\n\n// ── checkbox ─────────────────────────────────────────────────────────────────\n\nexport type RhfCheckboxProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> &\n Pick<CheckboxProps, \"inputClassName\" | \"autoFocus\" | \"aria-label\">;\n\n/**\n * The kit's {@link Checkbox}, label beside the box and `hint` under it (the\n * checkbox's own `description`). Stores a boolean. `required` is the native one here\n * — see Checkbox — so a `<form>` refuses to submit it unticked.\n */\nexport function RhfCheckbox<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n ...boxProps\n}: RhfCheckboxProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, required, disabled, excludeWhenDisabled, className }}\n showLabel={false}\n render={({ field, invalid }) => (\n <Checkbox\n {...boxProps}\n ref={field.ref}\n name={field.name}\n checked={Boolean(field.value)}\n onCheckedChange={field.onChange}\n onBlur={field.onBlur}\n disabled={field.disabled}\n required={required}\n invalid={invalid}\n label={label}\n description={hint}\n />\n )}\n />\n );\n}\n\n// ── comboboxes ───────────────────────────────────────────────────────────────\n\nexport type RhfComboboxProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n V extends string | number = string | number,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> &\n Pick<\n EntityComboboxProps<V>,\n | \"options\"\n | \"loadOptions\"\n | \"loading\"\n | \"placeholder\"\n | \"searchPlaceholder\"\n | \"emptyLabel\"\n | \"clearable\"\n | \"clearLabel\"\n | \"onCreate\"\n | \"createLabel\"\n | \"filter\"\n | \"minChars\"\n | \"debounceMs\"\n > & {\n /** What a clear stores — the picker's `clearValue`. Default `null`; `\"\"` for a\n * schema that spells \"no choice\" as an empty string. */\n clearValue?: ComboClearValue;\n /** Classes for the picker. */\n comboClassName?: string;\n };\n\nfunction EntityControl<V extends string | number>({\n field,\n invalid,\n required,\n error,\n id,\n describedBy,\n clearValue,\n comboClassName,\n comboProps,\n}: {\n field: ControllerRenderProps;\n invalid: boolean;\n required?: boolean;\n error: string | undefined;\n id: string;\n describedBy: string | undefined;\n clearValue: ComboClearValue;\n comboClassName?: string;\n comboProps: Omit<RhfComboboxProps<FieldValues, string, V>, keyof RhfFieldBaseProps | \"clearValue\" | \"comboClassName\">;\n}) {\n const box = useRef<HTMLDivElement>(null);\n // EntityCombobox puts `id` and the ARIA below on its trigger, so the label's\n // `htmlFor` names it, the hint describes it and the focus handle finds it by id.\n useFocusHandle(field.ref, () => document.getElementById(id));\n // EntityCombobox reports no blur: focus leaving the picker marks the field touched.\n const onBlur = field.onBlur;\n useLayoutEffect(() => {\n const el = box.current;\n if (!el) return;\n el.addEventListener(\"focusout\", onBlur);\n return () => el.removeEventListener(\"focusout\", onBlur);\n }, [onBlur]);\n const value: unknown = field.value;\n return (\n <div ref={box}>\n <EntityCombobox<V, ComboClearValue>\n {...comboProps}\n className={comboClassName}\n id={id}\n aria-describedby={describedBy}\n aria-required={required || undefined}\n value={(value ?? null) as V | ComboClearValue | null}\n clearValue={clearValue}\n onChange={(v) => field.onChange(v)}\n disabled={field.disabled}\n invalid={invalid}\n // Its own message, which it merges into the trigger's aria-describedby after\n // the hint.\n error={error}\n />\n </div>\n );\n}\n\n/**\n * The kit's {@link EntityCombobox}: an id-keyed pick from `options` or `loadOptions`.\n * Stores the option's `value`, or `clearValue` on a clear (only offered with\n * `clearable`).\n */\nexport function RhfCombobox<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n V extends string | number = string | number,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n clearValue = null,\n comboClassName,\n ...comboProps\n}: RhfComboboxProps<TFieldValues, TName, V, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n asControl={false}\n message={false}\n render={({ field, invalid, error, id, describedBy }) => (\n <EntityControl<V>\n field={field as unknown as ControllerRenderProps}\n invalid={invalid}\n required={required}\n error={error}\n id={id}\n describedBy={describedBy}\n clearValue={clearValue}\n comboClassName={comboClassName}\n comboProps={comboProps}\n />\n )}\n />\n );\n}\n\nexport type RhfTextComboboxProps<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n> = RhfFieldBaseProps<TFieldValues, TName, TTransformed> &\n Pick<\n ComboboxProps,\n | \"options\"\n | \"placeholder\"\n | \"groupBy\"\n | \"maxSuggestions\"\n | \"searchPlaceholder\"\n | \"createLabel\"\n | \"optionAdornment\"\n | \"autoFocus\"\n | \"aria-label\"\n > & {\n /** Classes for the combobox. */\n comboClassName?: string;\n };\n\n/**\n * The kit's free-text {@link Combobox}: type anything, or pick one of `options`.\n * Stores the string.\n */\nexport function RhfTextCombobox<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n TTransformed = TFieldValues,\n>({\n name,\n control,\n rules,\n label,\n hint,\n required,\n disabled,\n excludeWhenDisabled,\n className,\n comboClassName,\n ...comboProps\n}: RhfTextComboboxProps<TFieldValues, TName, TTransformed>) {\n return (\n <RhfField\n {...{ name, control, rules, label, hint, required, disabled, excludeWhenDisabled, className }}\n asControl={false}\n message={false}\n render={({ field, invalid, error, id, describedBy }) => (\n <TextComboControl\n field={field as unknown as ControllerRenderProps}\n invalid={invalid}\n required={required}\n error={error}\n id={id}\n describedBy={describedBy}\n className={comboClassName}\n comboProps={comboProps}\n />\n )}\n />\n );\n}\n\nfunction TextComboControl({\n field,\n invalid,\n required,\n error,\n id,\n describedBy,\n className,\n comboProps,\n}: {\n field: ControllerRenderProps;\n invalid: boolean;\n required?: boolean;\n error: string | undefined;\n id: string;\n describedBy: string | undefined;\n className?: string;\n comboProps: Omit<RhfTextComboboxProps, keyof RhfFieldBaseProps | \"comboClassName\">;\n}) {\n // The combobox routes `id` and its ARIA to its <input>, so the label's `htmlFor`\n // names it, the hint describes it and the focus handle finds it; the error is its\n // own `error` prop, which it merges in after the hint.\n useFocusHandle(field.ref, () => document.getElementById(id));\n const value: unknown = field.value;\n return (\n <Combobox\n {...comboProps}\n id={id}\n aria-describedby={describedBy}\n aria-required={required || undefined}\n className={className}\n value={typeof value === \"string\" ? value : value == null ? \"\" : String(value)}\n onChange={field.onChange}\n onBlur={field.onBlur}\n disabled={field.disabled}\n invalid={invalid}\n error={error}\n />\n );\n}\n"],"mappings":";AAmJI,cAkEI,YAlEJ;AAxGJ,SAAS,iBAAiB,QAAQ,gBAAmD;AAQrF,SAAS,aAAa,iBAAiB,WAAW,UAAU,WAAW,aAAa,oBAAoB;AACxG,SAAS,OAAO,QAAQ,gBAAuE;AAC/F,SAAS,mBAA0C;AACnD,SAAS,mBAAmB;AAC5B,SAAS,kBAAwC;AACjD,SAAS,gBAAoC;AAC7C,SAAS,sBAAgD;AACzD,SAAS,gBAAoC;AAE7C,SAAS,UAAU;AA8EnB,SAAS,WAAW,MAA0B;AAC5C,SAAO,SAAS,UAAa,SAAS,QAAQ,SAAS,SAAS,SAAS;AAC3E;AAIA,SAAS,SAAS,EAAE,UAAU,SAAS,GAAgD;AACrF,QAAM,EAAE,GAAG,IAAI,aAAa;AAC5B,SACE,oBAAC,aAAU,IAAI,GAAG,EAAE,UAAU,UAC3B,UACH;AAEJ;AAEA,SAAS,YAAqF;AAAA,EAC5F;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKG;AACD,QAAM,EAAE,IAAI,YAAY,YAAY,IAAI,aAAa;AACrD,QAAM,UAAU,OAAO;AAAA,IACrB;AAAA,IACA;AAAA,IACA,SAAS,WAAW;AAAA,IACpB,OAAO,WAAW,OAAO;AAAA,IACzB,IAAI;AAAA,IACJ,SAAS,GAAG,EAAE;AAAA,IACd;AAAA,EACF,CAAC;AACD,SAAO,YAAY,oBAAC,eAAa,mBAAQ,IAAiB;AAC5D;AAYO,SAAS,SAId;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,YAAY;AACd,GAAqD;AACnD,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU,sBAAsB,WAAW;AAAA,MAC3C,QAAQ,CAAC,EAAE,OAAO,WAAW,MAC3B,qBAAC,YAAS,WACP;AAAA,qBAAa,WAAW,KAAK,KAAK,oBAAC,YAAS,UAAqB,iBAAM;AAAA,QACxE;AAAA,UAAC;AAAA;AAAA,YACC,OAAO,YAAY,CAAC,MAAM,WAAW,EAAE,GAAG,OAAO,UAAU,KAAK,IAAI;AAAA,YACpE;AAAA,YACA;AAAA,YACA;AAAA;AAAA,QACF;AAAA,QACC,WAAW,IAAI,KAAK,oBAAC,mBAAiB,gBAAK;AAAA,QAC3C,WAAW,oBAAC,eAAY;AAAA,SAC3B;AAAA;AAAA,EAEJ;AAEJ;AAOA,SAAS,eAAe,KAAmC,MAA4C;AACrG,QAAM,UAAU,OAAO,IAAI;AAC3B,kBAAgB,MAAM;AACpB,YAAQ,UAAU;AAAA,EACpB,CAAC;AACD,kBAAgB,MAAM;AACpB,QAAI,EAAE,OAAO,MAAM,QAAQ,QAAQ,GAAG,MAAM,EAAE,CAAC;AAAA,EACjD,GAAG,CAAC,GAAG,CAAC;AACV;AAyBO,SAAS,aAId;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAyD;AACvD,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG,EAAE,MAAM,SAAS,OAAO,OAAO,MAAM,UAAU,UAAU,qBAAqB,UAAU;AAAA,MAC5F,QAAQ,CAAC,EAAE,OAAO,QAAQ,MACxB;AAAA,QAAC;AAAA;AAAA,UACC,iBAAe,YAAY;AAAA,UAC1B,GAAG;AAAA,UACJ,MAAM,MAAM;AAAA,UACZ,KAAK,MAAM;AAAA,UACX,OAAQ,MAAM,SAAS;AAAA,UACvB,UAAU,MAAM;AAAA,UAChB,QAAQ,MAAM;AAAA,UACd,UAAU,MAAM;AAAA,UAChB;AAAA;AAAA,MACF;AAAA;AAAA,EAEJ;AAEJ;AAiBO,SAAS,YAId;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAwD;AACtD,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG,EAAE,MAAM,SAAS,OAAO,OAAO,MAAM,UAAU,UAAU,qBAAqB,UAAU;AAAA,MAC5F,QAAQ,CAAC,EAAE,OAAO,QAAQ,MACxB;AAAA,QAAC;AAAA;AAAA,UACC,iBAAe,YAAY;AAAA,UAC1B,GAAG;AAAA,UACJ,WAAW;AAAA,UACX,MAAM,MAAM;AAAA,UACZ,KAAK,MAAM;AAAA,UACX,OAAQ,MAAM,SAAS;AAAA,UACvB,UAAU,MAAM;AAAA,UAChB,QAAQ,MAAM;AAAA,UACd,UAAU,MAAM;AAAA,UAChB;AAAA;AAAA,MACF;AAAA;AAAA,EAEJ;AAEJ;AAMA,SAAS,SAAS,OAA+B;AAC/C,MAAI,UAAU,QAAQ,UAAU,UAAa,UAAU,GAAI,QAAO;AAClE,QAAM,IAAI,OAAO,UAAU,WAAW,QAAQ,OAAO,OAAO,KAAK,EAAE,QAAQ,KAAK,GAAG,CAAC;AACpF,SAAO,OAAO,SAAS,CAAC,IAAI,IAAI;AAClC;AAmCO,SAAS,eAId;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EACb,WAAW;AAAA,EACX,GAAG;AACL,GAA2D;AACzD,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG,EAAE,MAAM,SAAS,OAAO,OAAO,MAAM,UAAU,UAAU,qBAAqB,UAAU;AAAA,MAC5F,QAAQ,CAAC,EAAE,OAAO,SAAS,GAAG;AAAA;AAAA;AAAA,QAG5B;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA;AAAA,QACF;AAAA;AAAA;AAAA,EAEJ;AAEJ;AAEA,SAAS,cAAc;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAUG;AAGD,iBAAe,MAAM,KAAK,MAAM,SAAS,eAAe,EAAE,CAAC;AAC3D,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ,oBAAkB,KAAK,kBAAkB;AAAA,MACzC,gBAAc,KAAK,cAAc;AAAA,MACjC,iBAAe,YAAY;AAAA,MAC3B;AAAA,MACA,OAAO,SAAS,MAAM,KAAK;AAAA,MAC3B,UAAU,CAAC,MAAM;AACf,cAAM,SAAS,KAAK,UAAU;AAC9B,cAAM,OAAO;AAAA,MACf;AAAA,MACA;AAAA,MACA,UAAU,MAAM;AAAA,MAChB;AAAA;AAAA,EACF;AAEJ;AAwBO,SAAS,gBAId,OAAgE;AAIhE,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ,QAAQ,MAAM,UAAU;AAAA,MACxB,YAAY,MAAM,cAAc;AAAA,MAChC,YAAY,MAAM,eAAe,SAAY,KAAK,MAAM;AAAA;AAAA,EAC1D;AAEJ;AAyCA,SAAS,YAAY,MAAyC;AAC5D,QAAM,UAAU,KAAK,KAAK;AAC1B,MAAI,YAAY,GAAI,QAAO;AAC3B,MAAI,CAAC,kBAAkB,KAAK,OAAO,EAAG,QAAO;AAC7C,QAAM,IAAI,OAAO,QAAQ,QAAQ,KAAK,GAAG,CAAC;AAC1C,SAAO,OAAO,SAAS,CAAC,IAAI,IAAI;AAClC;AAEA,SAAS,aAAa;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAOG;AACD,QAAM,EAAE,UAAU,UAAU,aAAa,MAAM,WAAW,GAAG,YAAY,IAAI;AAC7E,QAAM,QAAiB,MAAM;AAC7B,QAAM,WAAW,UAAU,QAAQ,UAAU,SAAY,KAAK,OAAO,KAAK;AAI1E,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,QAAQ;AAC3C,QAAM,CAAC,MAAM,OAAO,IAAI,SAAkB,KAAK;AAC/C,MAAI,SAAS,OAAO;AAClB,YAAQ,KAAK;AACb,UAAM,UAAU,YAAY,WAAW,QAAQ,YAAY,KAAK;AAChE,UAAM,OAAO,YAAY,WAAW,YAAY,WAAW,YAAY,SAAS,KAAK;AACrF,QAAI,CAAC,KAAM,UAAS,QAAQ;AAAA,EAC9B;AACA,QAAM,QAAQ,OAAgC,IAAI;AAGlD,QAAM,SAAS,MAAM;AACrB,kBAAgB,MAAM;AACpB,UAAM,KAAK,MAAM;AACjB,QAAI,CAAC,GAAI;AACT,OAAG,iBAAiB,QAAQ,MAAM;AAClC,WAAO,MAAM,GAAG,oBAAoB,QAAQ,MAAM;AAAA,EACpD,GAAG,CAAC,MAAM,CAAC;AACX,SACE,oBAAC,SACC;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ;AAAA,MACA;AAAA,MACA,oBAAkB;AAAA,MAClB,iBAAe,YAAY;AAAA,MAC3B,KAAK,CAAC,OAAO;AACX,cAAM,UAAU;AAChB,cAAM,IAAI,EAAE;AAAA,MACd;AAAA,MACA,OAAO;AAAA,MACP,UAAU,MAAM;AAAA,MAChB;AAAA,MACA,UAAU,CAAC,SAAS;AAClB,iBAAS,IAAI;AACb,YAAI,YAAY,UAAU;AACxB,gBAAM,SAAS,IAAI;AACnB;AAAA,QACF;AACA,cAAM,SAAS,YAAY,IAAI;AAC/B,YAAI,WAAW,OAAW;AAC1B,cAAM,SAAS,UAAU,UAAU;AAAA,MACrC;AAAA;AAAA,EACF,GACF;AAEJ;AAOO,SAAS,cAId;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAA0D;AACxD,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG,EAAE,MAAM,SAAS,OAAO,OAAO,MAAM,UAAU,UAAU,qBAAqB,UAAU;AAAA,MAC5F,WAAW;AAAA,MACX,QAAQ,CAAC,EAAE,OAAO,SAAS,IAAI,YAAY,MACzC;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,OAAO;AAAA;AAAA,MACT;AAAA;AAAA,EAEJ;AAEJ;AAiBA,SAAS,YAAY;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAUG;AACD,iBAAe,MAAM,KAAK,MAAM,SAAS,eAAe,EAAE,CAAC;AAC3D,QAAM,QAAiB,MAAM;AAC7B,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACH,GAAG;AAAA,MACJ,iBAAe,YAAY;AAAA,MAC3B;AAAA,MACA,OAAO,OAAO,UAAU,WAAW,QAAQ;AAAA,MAC3C,UAAU,CAAC,QAAQ;AACjB,cAAM,SAAS,QAAQ,KAAK,aAAa,GAAG;AAC5C,cAAM,OAAO;AAAA,MACf;AAAA,MACA,UAAU,MAAM;AAAA,MAChB;AAAA,MACA,WAAW,kBAAkB;AAAA;AAAA,EAC/B;AAEJ;AAGO,SAAS,aAId;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EACb,GAAG;AACL,GAAyD;AACvD,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG,EAAE,MAAM,SAAS,OAAO,OAAO,MAAM,UAAU,UAAU,qBAAqB,UAAU;AAAA,MAC5F,QAAQ,CAAC,EAAE,OAAO,SAAS,GAAG;AAAA;AAAA;AAAA,QAG5B;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA;AAAA,QACF;AAAA;AAAA;AAAA,EAEJ;AAEJ;AA6BO,SAAS,UAId;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAsD;AACpD,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG,EAAE,MAAM,SAAS,OAAO,OAAO,MAAM,UAAU,UAAU,qBAAqB,UAAU;AAAA,MAC5F,QAAQ,CAAC,EAAE,OAAO,QAAQ,MACxB;AAAA,QAAC;AAAA;AAAA,UACC,iBAAe,YAAY;AAAA,UAC1B,GAAG;AAAA,UACJ,WAAW,GAAG,UAAU,eAAe;AAAA,UACvC,MAAM,MAAM;AAAA,UACZ,KAAK,MAAM;AAAA,UACX,OAAQ,MAAM,SAAS;AAAA,UACvB,UAAU,CAAC,MAAM;AACf,kBAAM,MAAM,EAAE,OAAO;AACrB,kBAAM,SAAS,iBAAiB,QAAQ,KAAK,OAAO,GAAG,IAAI,GAAG;AAAA,UAChE;AAAA,UACA,QAAQ,MAAM;AAAA,UACd,UAAU,MAAM;AAAA,UAChB;AAAA,UAEC;AAAA,4BAAgB,UAAa,oBAAC,YAAO,OAAM,IAAI,uBAAY;AAAA,YAC3D,UACG,QAAQ,IAAI,CAAC,MACX,oBAAC,YAA6B,OAAO,EAAE,OAAO,UAAU,EAAE,UACvD,YAAE,SADQ,OAAO,EAAE,KAAK,CAE3B,CACD,IACD;AAAA;AAAA;AAAA,MACN;AAAA;AAAA,EAEJ;AAEJ;AAgBO,SAAS,YAId;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAwD;AACtD,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG,EAAE,MAAM,SAAS,OAAO,UAAU,UAAU,qBAAqB,UAAU;AAAA,MAC/E,WAAW;AAAA,MACX,QAAQ,CAAC,EAAE,OAAO,QAAQ,MACxB;AAAA,QAAC;AAAA;AAAA,UACE,GAAG;AAAA,UACJ,KAAK,MAAM;AAAA,UACX,MAAM,MAAM;AAAA,UACZ,SAAS,QAAQ,MAAM,KAAK;AAAA,UAC5B,iBAAiB,MAAM;AAAA,UACvB,QAAQ,MAAM;AAAA,UACd,UAAU,MAAM;AAAA,UAChB;AAAA,UACA;AAAA,UACA;AAAA,UACA,aAAa;AAAA;AAAA,MACf;AAAA;AAAA,EAEJ;AAEJ;AAiCA,SAAS,cAAyC;AAAA,EAChD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAUG;AACD,QAAM,MAAM,OAAuB,IAAI;AAGvC,iBAAe,MAAM,KAAK,MAAM,SAAS,eAAe,EAAE,CAAC;AAE3D,QAAM,SAAS,MAAM;AACrB,kBAAgB,MAAM;AACpB,UAAM,KAAK,IAAI;AACf,QAAI,CAAC,GAAI;AACT,OAAG,iBAAiB,YAAY,MAAM;AACtC,WAAO,MAAM,GAAG,oBAAoB,YAAY,MAAM;AAAA,EACxD,GAAG,CAAC,MAAM,CAAC;AACX,QAAM,QAAiB,MAAM;AAC7B,SACE,oBAAC,SAAI,KAAK,KACR;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ,WAAW;AAAA,MACX;AAAA,MACA,oBAAkB;AAAA,MAClB,iBAAe,YAAY;AAAA,MAC3B,OAAQ,SAAS;AAAA,MACjB;AAAA,MACA,UAAU,CAAC,MAAM,MAAM,SAAS,CAAC;AAAA,MACjC,UAAU,MAAM;AAAA,MAChB;AAAA,MAGA;AAAA;AAAA,EACF,GACF;AAEJ;AAOO,SAAS,YAKd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EACb;AAAA,EACA,GAAG;AACL,GAA2D;AACzD,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG,EAAE,MAAM,SAAS,OAAO,OAAO,MAAM,UAAU,UAAU,qBAAqB,UAAU;AAAA,MAC5F,WAAW;AAAA,MACX,SAAS;AAAA,MACT,QAAQ,CAAC,EAAE,OAAO,SAAS,OAAO,IAAI,YAAY,MAChD;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA;AAAA,MACF;AAAA;AAAA,EAEJ;AAEJ;AA2BO,SAAS,gBAId;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAA4D;AAC1D,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG,EAAE,MAAM,SAAS,OAAO,OAAO,MAAM,UAAU,UAAU,qBAAqB,UAAU;AAAA,MAC5F,WAAW;AAAA,MACX,SAAS;AAAA,MACT,QAAQ,CAAC,EAAE,OAAO,SAAS,OAAO,IAAI,YAAY,MAChD;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,WAAW;AAAA,UACX;AAAA;AAAA,MACF;AAAA;AAAA,EAEJ;AAEJ;AAEA,SAAS,iBAAiB;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GASG;AAID,iBAAe,MAAM,KAAK,MAAM,SAAS,eAAe,EAAE,CAAC;AAC3D,QAAM,QAAiB,MAAM;AAC7B,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ;AAAA,MACA,oBAAkB;AAAA,MAClB,iBAAe,YAAY;AAAA,MAC3B;AAAA,MACA,OAAO,OAAO,UAAU,WAAW,QAAQ,SAAS,OAAO,KAAK,OAAO,KAAK;AAAA,MAC5E,UAAU,MAAM;AAAA,MAChB,QAAQ,MAAM;AAAA,MACd,UAAU,MAAM;AAAA,MAChB;AAAA,MACA;AAAA;AAAA,EACF;AAEJ;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eifi1/ui-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "App-agnostic shared design system: domain-free React components, theme and tokens.",
|
|
6
6
|
"_sideEffects": "The barrel (src/index.ts) re-exports EVERY component, including components/chart, which statically imports recharts. Without this field a bundler must assume each of those modules has side effects, so it cannot drop the unused ones: importing a Button from '@eifi1/ui-kit' dragged all 433KB of recharts into the consumer's ENTRY chunk, and Keksdose was preloading it on every page load, login included. Nothing in src/ imports for side effects (no bare imports, no CSS imports from JS, no module-level global writes) — the token stylesheet is its own './tokens.css' export — so this is safe. CSS is still listed so any future stylesheet survives. Re-checked when `flag-icons` left `dependencies` and tsup started emitting a `\"use client\"` banner: neither touches this. The flag stylesheet was never imported from JS in the first place (that was the finding), and a directive prologue is a string literal every bundler lifts out before it decides whether a module is inert.",
|