@eifi1/ui-kit 0.13.1 → 0.14.1
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/error-boundary.d.ts +8 -1
- package/dist/components/error-boundary.js +4 -1
- package/dist/components/error-boundary.js.map +1 -1
- package/dist/components/page-header.d.ts +57 -2
- package/dist/components/page-header.js +50 -8
- package/dist/components/page-header.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/package.json +1 -1
- package/src/components/error-boundary.tsx +16 -2
- package/src/components/page-header.tsx +117 -4
- 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
|
@@ -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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eifi1/ui-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.1",
|
|
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.",
|
|
@@ -151,6 +151,9 @@ export interface CrashReport {
|
|
|
151
151
|
userAgent: string;
|
|
152
152
|
/** The boundary's `appVersion` prop. */
|
|
153
153
|
appVersion?: string;
|
|
154
|
+
/** The boundary's `placement` prop ("app", "page", "widget"): which boundary caught
|
|
155
|
+
* it, so triage can tell a whole-app crash from one page's (keksdose G3b). */
|
|
156
|
+
placement?: string;
|
|
154
157
|
/** `navigator.onLine` at the moment of the crash; left out where there is none. */
|
|
155
158
|
online?: boolean;
|
|
156
159
|
/** {@link isChunkLoadError} of the thrown value. Such a crash is never handed to
|
|
@@ -177,6 +180,7 @@ export function formatCrashReport(report: CrashReport): string {
|
|
|
177
180
|
`User agent: ${report.userAgent}`,
|
|
178
181
|
];
|
|
179
182
|
if (report.appVersion) lines.push(`App version: ${report.appVersion}`);
|
|
183
|
+
if (report.placement) lines.push(`Placement: ${report.placement}`);
|
|
180
184
|
if (report.online === false) lines.push("Online: no");
|
|
181
185
|
for (const [key, value] of Object.entries(report.extras)) lines.push(`${key}: ${value}`);
|
|
182
186
|
if (report.stack) lines.push("", "Stack:", report.stack.trim());
|
|
@@ -194,9 +198,14 @@ export function formatCrashReport(report: CrashReport): string {
|
|
|
194
198
|
* times a second. The page and the time are left out on purpose: the same bug on two
|
|
195
199
|
* routes is still one bug.
|
|
196
200
|
*/
|
|
197
|
-
export function crashFingerprint(
|
|
201
|
+
export function crashFingerprint(
|
|
202
|
+
report: Pick<CrashReport, "name" | "message" | "stack"> & Pick<Partial<CrashReport>, "placement">,
|
|
203
|
+
): string {
|
|
198
204
|
const frames = (report.stack ?? "").split("\n").slice(0, 4).join("|");
|
|
199
|
-
|
|
205
|
+
// The placement is part of it (keksdose G3b): the same error caught by the page
|
|
206
|
+
// boundary and, after Try again fails, by the app boundary is two facts for triage.
|
|
207
|
+
const where = report.placement ? `${report.placement}::` : "";
|
|
208
|
+
return `${where}${report.name}::${report.message}::${frames}`;
|
|
200
209
|
}
|
|
201
210
|
|
|
202
211
|
/**
|
|
@@ -321,6 +330,10 @@ export interface ErrorBoundaryProps {
|
|
|
321
330
|
copyReport?: boolean;
|
|
322
331
|
/** The app's version, printed in the report — the first question on every crash. */
|
|
323
332
|
appVersion?: string;
|
|
333
|
+
/** Which boundary this is — "app" at the root, "page" in the layout — carried into
|
|
334
|
+
* the report (`placement`) and its fingerprint, so `onReport` needs no closure to say
|
|
335
|
+
* where the crash was caught (keksdose G3b). */
|
|
336
|
+
placement?: string;
|
|
324
337
|
/** More `key: value` lines for the report, read when the boundary catches (a tenant
|
|
325
338
|
* id, the feature flags). A throw from it is swallowed and the lines are left out. */
|
|
326
339
|
reportExtras?: () => Record<string, string>;
|
|
@@ -427,6 +440,7 @@ function buildReport(details: ErrorBoundaryDetails, componentStack: string | und
|
|
|
427
440
|
time: new Date().toISOString(),
|
|
428
441
|
userAgent,
|
|
429
442
|
appVersion: props.appVersion,
|
|
443
|
+
placement: props.placement,
|
|
430
444
|
online,
|
|
431
445
|
chunkLoad: isChunkLoadError(details),
|
|
432
446
|
extras,
|
|
@@ -34,6 +34,25 @@ const ROW: Record<PageHeaderMobileLayout, string> = {
|
|
|
34
34
|
inline: "flex-row items-center justify-between gap-2 sm:gap-4",
|
|
35
35
|
};
|
|
36
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Where the actions sit on the title block's height, in the one row the header is from
|
|
39
|
+
* `sm` up (and on a phone too when {@link PageHeaderMobileLayout} is `inline`, the only
|
|
40
|
+
* layout that has a row there). Unset keeps each layout's own: `start` for `stacked`,
|
|
41
|
+
* `center` for `inline`.
|
|
42
|
+
*/
|
|
43
|
+
export type PageHeaderActionsAlign = "start" | "center" | "end";
|
|
44
|
+
|
|
45
|
+
/** Applied to the ROW, so the title block and the actions are aligned against each
|
|
46
|
+
* other on one cross axis. 0.14.0 put `self-*` on the actions box alone, which moved
|
|
47
|
+
* nothing when the actions were the taller item — they already filled the row, and
|
|
48
|
+
* the title stayed at the top (keksdose H2, reports-page's two-line labelled
|
|
49
|
+
* CurrencySelect). Per layout, because `stacked` is a column on a phone, where
|
|
50
|
+
* `items-center` would centre everything HORIZONTALLY — so it aligns from `sm` up. */
|
|
51
|
+
const ROW_ALIGN: Record<PageHeaderMobileLayout, Record<PageHeaderActionsAlign, string>> = {
|
|
52
|
+
stacked: { start: "sm:items-start", center: "sm:items-center", end: "sm:items-end" },
|
|
53
|
+
inline: { start: "items-start", center: "items-center", end: "items-end" },
|
|
54
|
+
};
|
|
55
|
+
|
|
37
56
|
export interface PageHeaderProps extends Omit<ComponentPropsWithoutRef<"div">, "title"> {
|
|
38
57
|
title: ReactNode;
|
|
39
58
|
/** A sentence under the title. */
|
|
@@ -63,6 +82,54 @@ export interface PageHeaderProps extends Omit<ComponentPropsWithoutRef<"div">, "
|
|
|
63
82
|
* button, a month picker); a long title wraps to make room for them instead.
|
|
64
83
|
*/
|
|
65
84
|
mobileLayout?: PageHeaderMobileLayout;
|
|
85
|
+
/**
|
|
86
|
+
* A second group of actions that gets its OWN full-width row under the header on a
|
|
87
|
+
* phone, and joins the actions' row from `sm` up, between the title and
|
|
88
|
+
* {@link actions}.
|
|
89
|
+
*
|
|
90
|
+
* keksdose's budget page (budget-page.tsx, feedback #60) is the case: title and month
|
|
91
|
+
* navigation on row 1, the fold/unfold toggles on row 2 on a phone — "two tidy rows
|
|
92
|
+
* instead of the old ragged justify-between overflow" — and one row, title | toggles |
|
|
93
|
+
* month nav, on a wider screen. It builds that by hand with a wrapping flex row and
|
|
94
|
+
* swapped order utilities; adopting `PageHeader` (keksdose G6b) must not lose it.
|
|
95
|
+
* There: `actions` is the month navigation, this is the toggles.
|
|
96
|
+
*
|
|
97
|
+
* The DOM order is title, `actions`, `secondaryActions` — the phone's visual order,
|
|
98
|
+
* and the one a screen reader and the Tab key follow at every width. From `sm` up the
|
|
99
|
+
* two groups swap places visually only, which keeps the page's primary control (the
|
|
100
|
+
* month) at the row's end, where keksdose had it, and first in reading order. The
|
|
101
|
+
* breakpoint is `sm`, the one {@link mobileLayout} switches at, not keksdose's `md`:
|
|
102
|
+
* one header, one breakpoint.
|
|
103
|
+
*/
|
|
104
|
+
secondaryActions?: ReactNode;
|
|
105
|
+
/**
|
|
106
|
+
* The actions' vertical alignment against the title block — see
|
|
107
|
+
* {@link PageHeaderActionsAlign}. Unset keeps the layout's own.
|
|
108
|
+
*
|
|
109
|
+
* keksdose's reports page (reports-page.tsx, keksdose G8) carries a LABELLED
|
|
110
|
+
* `CurrencySelect` as its action: a field with its label on top is taller than the
|
|
111
|
+
* title, and `stacked`'s default top alignment hangs it from the title's cap height
|
|
112
|
+
* with its control well below the title's line. `center` sets it on the title's
|
|
113
|
+
* middle, as that page's hand-written `items-center` row did. It aligns the whole row
|
|
114
|
+
* (title block and actions against each other), since 0.14.1: 0.14.0 moved only the
|
|
115
|
+
* actions box, which did nothing when the actions were the taller item (keksdose H2).
|
|
116
|
+
*/
|
|
117
|
+
actionsAlign?: PageHeaderActionsAlign;
|
|
118
|
+
/**
|
|
119
|
+
* One line, cut with an ellipsis, instead of the default breaking of a long word onto
|
|
120
|
+
* as many lines as it needs.
|
|
121
|
+
*
|
|
122
|
+
* keksdose's payees page (payees-page.tsx, live #263, keksdose G6a) wraps its title in
|
|
123
|
+
* its own truncating span so a long name gives way to the `inline` header's actions
|
|
124
|
+
* instead of pushing them. This is that span's behaviour on the heading itself; the
|
|
125
|
+
* title block is already allowed to shrink below its content, which is what lets the
|
|
126
|
+
* cut happen inside a flex row.
|
|
127
|
+
*
|
|
128
|
+
* The full title stays in the DOM as the heading's text, so a screen reader and the
|
|
129
|
+
* document outline read all of it. There is deliberately no native `title` tooltip:
|
|
130
|
+
* the kit does not use them (not on touch, not on keyboard focus, not styled).
|
|
131
|
+
*/
|
|
132
|
+
truncateTitle?: boolean;
|
|
66
133
|
}
|
|
67
134
|
|
|
68
135
|
/**
|
|
@@ -85,20 +152,66 @@ export function PageHeader({
|
|
|
85
152
|
as = "h1",
|
|
86
153
|
size = "md",
|
|
87
154
|
mobileLayout = "stacked",
|
|
155
|
+
secondaryActions,
|
|
156
|
+
actionsAlign,
|
|
157
|
+
truncateTitle = false,
|
|
88
158
|
className,
|
|
89
159
|
...rest
|
|
90
160
|
}: PageHeaderProps) {
|
|
91
161
|
const Heading = as as ElementType;
|
|
162
|
+
const hasSecondary = secondaryActions != null;
|
|
163
|
+
const wrapsSecondary = hasSecondary && mobileLayout === "inline";
|
|
164
|
+
const align = actionsAlign != null ? ROW_ALIGN[mobileLayout][actionsAlign] : undefined;
|
|
165
|
+
// keksdose H1: in `inline` the title block could shrink below its longest word, and
|
|
166
|
+
// `break-words` then split "Monatsbudget" into "Monatsbudg" / "et" beside the actions.
|
|
167
|
+
// Unless it truncates, the title keeps its longest word (min-content) and the ROW
|
|
168
|
+
// wraps instead: actions that do not fit go to a line of their own, as the app's old
|
|
169
|
+
// `flex-wrap` header did.
|
|
170
|
+
const keepsWords = mobileLayout === "inline" && !truncateTitle;
|
|
92
171
|
return (
|
|
93
172
|
<div {...rest} className={cn("flex min-w-0 flex-col gap-2", className)}>
|
|
94
173
|
{breadcrumbs}
|
|
95
|
-
|
|
96
|
-
|
|
174
|
+
{/* With a second group, `inline` wraps so that group's full-width basis puts it
|
|
175
|
+
on a row of its own on a phone (`stacked` is a column there already, and a
|
|
176
|
+
basis would size a column item's HEIGHT); from `sm` up the row stops wrapping
|
|
177
|
+
and the order utilities seat it between the title and the actions. Without
|
|
178
|
+
one, nothing changes. */}
|
|
179
|
+
<div
|
|
180
|
+
className={cn(
|
|
181
|
+
"flex min-w-0",
|
|
182
|
+
ROW[mobileLayout],
|
|
183
|
+
keepsWords ? "flex-wrap" : wrapsSecondary && "flex-wrap sm:flex-nowrap",
|
|
184
|
+
align,
|
|
185
|
+
)}
|
|
186
|
+
>
|
|
187
|
+
<div className={cn("flex-1", keepsWords ? "min-w-min" : "min-w-0")}>
|
|
97
188
|
{eyebrow != null && <p className={cn(SECTION_LABEL_CLASS.xs, "mb-1")}>{eyebrow}</p>}
|
|
98
|
-
<Heading
|
|
189
|
+
<Heading
|
|
190
|
+
className={cn(
|
|
191
|
+
truncateTitle ? "truncate" : "break-words",
|
|
192
|
+
"text-[var(--text-primary)]",
|
|
193
|
+
TITLE[size],
|
|
194
|
+
)}
|
|
195
|
+
>
|
|
196
|
+
{title}
|
|
197
|
+
</Heading>
|
|
99
198
|
{description != null && <p className="mt-1 text-sm text-[var(--text-muted)]">{description}</p>}
|
|
100
199
|
</div>
|
|
101
|
-
{actions != null &&
|
|
200
|
+
{actions != null && (
|
|
201
|
+
<div className={cn("flex shrink-0 flex-wrap items-center gap-2", hasSecondary && "sm:order-2")}>
|
|
202
|
+
{actions}
|
|
203
|
+
</div>
|
|
204
|
+
)}
|
|
205
|
+
{hasSecondary && (
|
|
206
|
+
<div
|
|
207
|
+
className={cn(
|
|
208
|
+
"flex flex-wrap items-center gap-2 sm:order-1 sm:shrink-0",
|
|
209
|
+
wrapsSecondary && "basis-full sm:basis-auto",
|
|
210
|
+
)}
|
|
211
|
+
>
|
|
212
|
+
{secondaryActions}
|
|
213
|
+
</div>
|
|
214
|
+
)}
|
|
102
215
|
</div>
|
|
103
216
|
</div>
|
|
104
217
|
);
|
|
@@ -50,8 +50,11 @@ function physicalSide(side: TooltipSide, dir: Direction): PhysicalSide {
|
|
|
50
50
|
* the viewport as well, for narrow screens where 20rem is already most of it.
|
|
51
51
|
* `side` is a preference rather than an instruction for the PORTALLED variant,
|
|
52
52
|
* which measures the bubble and turns it round when it would not fit
|
|
53
|
-
* (Steering Design feedback #126). The CSS-
|
|
54
|
-
*
|
|
53
|
+
* (Steering Design feedback #126). The CSS-placed one never turns round, so there
|
|
54
|
+
* `side` is still the whole of which side it is on — but since 0.14 it is slid back
|
|
55
|
+
* along the cross axis when it would cross the viewport edge (keksdose G7), which the
|
|
56
|
+
* viewport term in this cap is what makes possible: a bubble never wider than the glass
|
|
57
|
+
* minus the margins always fits once slid. */
|
|
55
58
|
const TOOLTIP_SURFACE =
|
|
56
59
|
"w-max max-w-[min(20rem,calc(100vw-1rem))] rounded-md border border-[var(--border)] bg-[var(--bg-surface)] px-2 py-1 text-xs font-medium text-[var(--text-primary)] shadow-lg";
|
|
57
60
|
|
|
@@ -220,6 +223,37 @@ type TooltipVariantProps = Omit<TooltipProps, "side" | "portal" | "lazy"> & { si
|
|
|
220
223
|
* existing app tests find without a hover (see above): flipping it would turn every
|
|
221
224
|
* `getByRole("tooltip")` written against 0.12 into a failure in all three apps at once.
|
|
222
225
|
* Reach for `lazy` wherever a `portal` was pinned only to keep a test's DOM clean.
|
|
226
|
+
*
|
|
227
|
+
* ⚠️ **The in-place bubble is clamped to the viewport when it opens (keksdose G7).** The
|
|
228
|
+
* portalled bubble has always measured itself and been pushed back onto the glass
|
|
229
|
+
* ({@link placeTooltip}); the in-place one never learnt its own size, so `side` was the
|
|
230
|
+
* whole of its placement and a `top` / `bottom` bubble sat centred on its trigger
|
|
231
|
+
* whatever that cost. The cost shows on a phone: long labels live at a row's START edge
|
|
232
|
+
* — a gcloud command in keksdose's jobs panel, a canned reply in a support thread — and
|
|
233
|
+
* a 20rem bubble centred on a trigger 16px from the edge hangs half its text off the
|
|
234
|
+
* screen. keksdose pinned `portal` on those sites for that alone, which gave up `lazy`'s
|
|
235
|
+
* point (the cheap, in-place bubble) to buy a placement.
|
|
236
|
+
*
|
|
237
|
+
* So now, when an in-place bubble goes up (default or `lazy`), a layout effect measures
|
|
238
|
+
* it and, if it crosses the viewport edge minus the same margin the portalled bubble
|
|
239
|
+
* keeps, slides it back along its CROSS axis only — sideways for `top` / `bottom`, up or
|
|
240
|
+
* down for the four side placements — with an inline `transform`, which composes with the
|
|
241
|
+
* placement classes' own `translate`. The main axis is left alone on purpose: sliding a
|
|
242
|
+
* `start` bubble along the main axis would slide it over its own trigger, and turning it
|
|
243
|
+
* round is a measured-placement decision this CSS-placed bubble does not make (pass
|
|
244
|
+
* `portal` for that). The width is already capped to the viewport (see
|
|
245
|
+
* `TOOLTIP_SURFACE`), so a bubble can always fit once slid, and a long label wraps
|
|
246
|
+
* instead of growing past the glass.
|
|
247
|
+
*
|
|
248
|
+
* Why on by default, with no prop? Because it is a no-op for every bubble that already
|
|
249
|
+
* fits — the shift is zero unless the bubble would overflow — so the only placements it
|
|
250
|
+
* changes are ones that were broken. The maths is in physical viewport pixels, so it
|
|
251
|
+
* needs no `dir`: an RTL row puts its long label at the RIGHT edge and gets slid left by
|
|
252
|
+
* the same code. Under jsdom there is no layout — every rect is zero-sized — and a
|
|
253
|
+
* zero-sized bubble is taken to be unmeasured, so tests see no transform at all. It is
|
|
254
|
+
* measured on open (and when the label or side changes while open), not on every scroll:
|
|
255
|
+
* an in-place bubble follows its trigger for free, and a page that scrolls sideways under
|
|
256
|
+
* an open tooltip is not a case worth a listener per tooltip.
|
|
223
257
|
*/
|
|
224
258
|
export function Tooltip({
|
|
225
259
|
label,
|
|
@@ -300,6 +334,10 @@ function InPlaceTooltip({
|
|
|
300
334
|
const [dir, setDir] = useState<Direction>("ltr");
|
|
301
335
|
const open = (hovered || focused) && !dismissed;
|
|
302
336
|
useEscapeKey(() => setDismissed(true), open);
|
|
337
|
+
// keksdose G7: slide an open in-place bubble back onto the screen. See "The in-place
|
|
338
|
+
// bubble is clamped" on {@link Tooltip}.
|
|
339
|
+
const bubbleRef = useRef<HTMLSpanElement | null>(null);
|
|
340
|
+
const shift = useViewportClamp(bubbleRef, open && !clipped, side, label);
|
|
303
341
|
// At mount, before the first paint: the in-place bubble inside a scroller is the
|
|
304
342
|
// phantom-scroll bug whether or not anyone opens it.
|
|
305
343
|
useLayoutEffect(() => {
|
|
@@ -353,9 +391,11 @@ function InPlaceTooltip({
|
|
|
353
391
|
// CSS that shows it) that can disagree for a frame after Escape.
|
|
354
392
|
open && (
|
|
355
393
|
<span
|
|
394
|
+
ref={bubbleRef}
|
|
356
395
|
id={id}
|
|
357
396
|
role="tooltip"
|
|
358
397
|
data-private={redact ? "" : undefined}
|
|
398
|
+
style={shiftStyle(shift)}
|
|
359
399
|
className={cn(TOOLTIP_SURFACE, "pointer-events-none absolute z-50 opacity-100", sidePositionClass[side])}
|
|
360
400
|
>
|
|
361
401
|
{label}
|
|
@@ -363,8 +403,10 @@ function InPlaceTooltip({
|
|
|
363
403
|
)
|
|
364
404
|
) : (
|
|
365
405
|
<span
|
|
406
|
+
ref={bubbleRef}
|
|
366
407
|
id={id}
|
|
367
408
|
role="tooltip"
|
|
409
|
+
style={shiftStyle(shift)}
|
|
368
410
|
// The `hidden` ATTRIBUTE, not an opacity class: dismissing has to take the
|
|
369
411
|
// bubble out of the accessibility tree as well as off the screen, or a screen
|
|
370
412
|
// reader still reads out the description of a bubble the user just closed.
|
|
@@ -413,6 +455,71 @@ const TOOLTIP_GAP = 4;
|
|
|
413
455
|
* against the glass reads as clipped even when every character is on screen. */
|
|
414
456
|
const TOOLTIP_MARGIN = 4;
|
|
415
457
|
|
|
458
|
+
/** A cross-axis slide, in viewport pixels, for an in-place bubble. */
|
|
459
|
+
interface Shift {
|
|
460
|
+
x: number;
|
|
461
|
+
y: number;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
const NO_SHIFT: Shift = { x: 0, y: 0 };
|
|
465
|
+
|
|
466
|
+
/** How far to slide the span `[low, high]` so it sits inside `[TOOLTIP_MARGIN,
|
|
467
|
+
* extent - TOOLTIP_MARGIN]`. Zero when it already does. The start edge wins when the
|
|
468
|
+
* span is wider than the room — as in {@link clamp}, the start of a label is the half
|
|
469
|
+
* worth keeping (and the width cap means that only happens on a viewport narrower than
|
|
470
|
+
* twice the margin). */
|
|
471
|
+
function slideInto(low: number, high: number, extent: number): number {
|
|
472
|
+
if (low < TOOLTIP_MARGIN) return TOOLTIP_MARGIN - low;
|
|
473
|
+
if (high > extent - TOOLTIP_MARGIN) return Math.max(extent - TOOLTIP_MARGIN - high, TOOLTIP_MARGIN - low);
|
|
474
|
+
return 0;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* The in-place bubble's viewport clamp (keksdose G7): while `active`, measure the bubble
|
|
479
|
+
* in a LAYOUT effect — before paint, so there is no frame with the label off the screen —
|
|
480
|
+
* and return the cross-axis slide that brings it inside the viewport minus
|
|
481
|
+
* `TOOLTIP_MARGIN`. `top` / `bottom` slide along x; `left` / `right` / `start` / `end`
|
|
482
|
+
* along y. {@link NO_SHIFT} while closed, so the next open measures the bubble where the
|
|
483
|
+
* CSS alone puts it.
|
|
484
|
+
*
|
|
485
|
+
* The rect it reads already includes the slide it applied last time (a label that
|
|
486
|
+
* changed while open), so that slide is taken back out before deciding the new one.
|
|
487
|
+
* A zero-sized rect means no layout (jsdom, `display: none`) and leaves the bubble put.
|
|
488
|
+
*/
|
|
489
|
+
function useViewportClamp(
|
|
490
|
+
bubbleRef: RefObject<HTMLSpanElement | null>,
|
|
491
|
+
active: boolean,
|
|
492
|
+
side: TooltipSide,
|
|
493
|
+
label: ReactNode,
|
|
494
|
+
): Shift {
|
|
495
|
+
const [shift, setShift] = useState<Shift>(NO_SHIFT);
|
|
496
|
+
useLayoutEffect(() => {
|
|
497
|
+
const el = bubbleRef.current;
|
|
498
|
+
if (!active || !el) {
|
|
499
|
+
setShift(NO_SHIFT);
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
502
|
+
const r = el.getBoundingClientRect();
|
|
503
|
+
if (r.width === 0 && r.height === 0) return;
|
|
504
|
+
const horizontal = side === "top" || side === "bottom";
|
|
505
|
+
setShift((previous) => {
|
|
506
|
+
const next = horizontal
|
|
507
|
+
? { x: slideInto(r.left - previous.x, r.right - previous.x, window.innerWidth), y: 0 }
|
|
508
|
+
: { x: 0, y: slideInto(r.top - previous.y, r.bottom - previous.y, window.innerHeight) };
|
|
509
|
+
return next.x === previous.x && next.y === previous.y ? previous : next;
|
|
510
|
+
});
|
|
511
|
+
}, [bubbleRef, active, side, label]);
|
|
512
|
+
return shift;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/** The inline style for a slide: none at all when there is nothing to slide, so a bubble
|
|
516
|
+
* that fits renders exactly as it did before G7. `transform` rather than `translate`
|
|
517
|
+
* because the placement classes own the `translate` property (Tailwind v4's
|
|
518
|
+
* `-translate-x-1/2`); the two compose instead of one replacing the other. */
|
|
519
|
+
function shiftStyle(shift: Shift) {
|
|
520
|
+
return shift.x === 0 && shift.y === 0 ? undefined : { transform: `translate(${shift.x}px, ${shift.y}px)` };
|
|
521
|
+
}
|
|
522
|
+
|
|
416
523
|
const portalTransformBySide: Record<PhysicalSide, string> = {
|
|
417
524
|
right: "translate(0, -50%)",
|
|
418
525
|
left: "translate(-100%, -50%)",
|