ngwr 14.7.0 → 14.8.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/bar-chart/styles/_index.scss +1 -0
- package/calendar-heatmap/styles/_index.scss +1 -0
- package/cascader/styles/_rules.scss +86 -14
- package/date-picker/styles/_index.scss +30 -0
- package/density/styles/_index.scss +4 -2
- package/donut-chart/styles/_index.scss +10 -0
- package/dropdown/styles/_index.scss +67 -5
- package/event-calendar/styles/_index.scss +209 -35
- package/fesm2022/ngwr-bar-chart.mjs +29 -4
- package/fesm2022/ngwr-bar-chart.mjs.map +1 -1
- package/fesm2022/ngwr-calendar-heatmap.mjs +59 -4
- package/fesm2022/ngwr-calendar-heatmap.mjs.map +1 -1
- package/fesm2022/ngwr-cascader.mjs +2 -2
- package/fesm2022/ngwr-cascader.mjs.map +1 -1
- package/fesm2022/ngwr-checkbox.mjs +12 -2
- package/fesm2022/ngwr-checkbox.mjs.map +1 -1
- package/fesm2022/ngwr-date-picker.mjs +705 -46
- package/fesm2022/ngwr-date-picker.mjs.map +1 -1
- package/fesm2022/ngwr-donut-chart.mjs +46 -4
- package/fesm2022/ngwr-donut-chart.mjs.map +1 -1
- package/fesm2022/ngwr-dropdown.mjs +166 -17
- package/fesm2022/ngwr-dropdown.mjs.map +1 -1
- package/fesm2022/ngwr-event-calendar.mjs +9 -2
- package/fesm2022/ngwr-event-calendar.mjs.map +1 -1
- package/fesm2022/ngwr-form.mjs +52 -1
- package/fesm2022/ngwr-form.mjs.map +1 -1
- package/fesm2022/ngwr-gauge.mjs +33 -4
- package/fesm2022/ngwr-gauge.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-ar.mjs +2 -0
- package/fesm2022/ngwr-i18n-ar.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-cs.mjs +2 -0
- package/fesm2022/ngwr-i18n-cs.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-de.mjs +2 -0
- package/fesm2022/ngwr-i18n-de.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-en.mjs +5 -0
- package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-es.mjs +2 -0
- package/fesm2022/ngwr-i18n-es.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-fr.mjs +2 -0
- package/fesm2022/ngwr-i18n-fr.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-he.mjs +2 -0
- package/fesm2022/ngwr-i18n-he.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-hi.mjs +2 -0
- package/fesm2022/ngwr-i18n-hi.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-id.mjs +2 -0
- package/fesm2022/ngwr-i18n-id.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-it.mjs +2 -0
- package/fesm2022/ngwr-i18n-it.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-ja.mjs +2 -0
- package/fesm2022/ngwr-i18n-ja.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-ko.mjs +2 -0
- package/fesm2022/ngwr-i18n-ko.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-nl.mjs +2 -0
- package/fesm2022/ngwr-i18n-nl.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-pl.mjs +2 -0
- package/fesm2022/ngwr-i18n-pl.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-pt.mjs +2 -0
- package/fesm2022/ngwr-i18n-pt.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-ru.mjs +2 -0
- package/fesm2022/ngwr-i18n-ru.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-sv.mjs +2 -0
- package/fesm2022/ngwr-i18n-sv.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-tr.mjs +2 -0
- package/fesm2022/ngwr-i18n-tr.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-uk.mjs +2 -0
- package/fesm2022/ngwr-i18n-uk.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-vi.mjs +2 -0
- package/fesm2022/ngwr-i18n-vi.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-zh-TW.mjs +2 -0
- package/fesm2022/ngwr-i18n-zh-TW.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-zh.mjs +2 -0
- package/fesm2022/ngwr-i18n-zh.mjs.map +1 -1
- package/fesm2022/ngwr-input-number.mjs +12 -0
- package/fesm2022/ngwr-input-number.mjs.map +1 -1
- package/fesm2022/ngwr-line-chart.mjs +16 -5
- package/fesm2022/ngwr-line-chart.mjs.map +1 -1
- package/fesm2022/ngwr-meter-group-testing.mjs +7 -3
- package/fesm2022/ngwr-meter-group-testing.mjs.map +1 -1
- package/fesm2022/ngwr-meter-group.mjs +24 -4
- package/fesm2022/ngwr-meter-group.mjs.map +1 -1
- package/fesm2022/ngwr-page-header.mjs +10 -2
- package/fesm2022/ngwr-page-header.mjs.map +1 -1
- package/fesm2022/ngwr-popover.mjs +569 -7
- package/fesm2022/ngwr-popover.mjs.map +1 -1
- package/fesm2022/ngwr-sidebar.mjs +7 -0
- package/fesm2022/ngwr-sidebar.mjs.map +1 -1
- package/fesm2022/ngwr-sparkline.mjs +82 -8
- package/fesm2022/ngwr-sparkline.mjs.map +1 -1
- package/fesm2022/ngwr-table.mjs +1 -1
- package/fesm2022/ngwr-table.mjs.map +1 -1
- package/fesm2022/ngwr-toolbar.mjs +7 -0
- package/fesm2022/ngwr-toolbar.mjs.map +1 -1
- package/fesm2022/ngwr-version.mjs +1 -1
- package/fesm2022/ngwr-version.mjs.map +1 -1
- package/form/styles/_index.scss +11 -1
- package/gauge/styles/_index.scss +1 -0
- package/i18n/ar.json +3 -1
- package/i18n/cs.json +3 -1
- package/i18n/de.json +3 -1
- package/i18n/en.json +3 -1
- package/i18n/es.json +3 -1
- package/i18n/fr.json +3 -1
- package/i18n/he.json +3 -1
- package/i18n/hi.json +3 -1
- package/i18n/id.json +3 -1
- package/i18n/it.json +3 -1
- package/i18n/ja.json +3 -1
- package/i18n/ko.json +3 -1
- package/i18n/nl.json +3 -1
- package/i18n/pl.json +3 -1
- package/i18n/pt.json +3 -1
- package/i18n/ru.json +3 -1
- package/i18n/sv.json +3 -1
- package/i18n/tr.json +3 -1
- package/i18n/uk.json +3 -1
- package/i18n/vi.json +3 -1
- package/i18n/zh-TW.json +3 -1
- package/i18n/zh.json +3 -1
- package/input/styles/_index.scss +19 -0
- package/input-number/styles/_index.scss +69 -0
- package/line-chart/styles/_index.scss +30 -2
- package/llms-full.txt +3 -3
- package/meter-group/styles/_index.scss +1 -0
- package/overlay/styles/_arrow.scss +27 -2
- package/package.json +1 -1
- package/page-header/styles/_index.scss +37 -1
- package/pagination/styles/_index.scss +9 -5
- package/popover/styles/_index.scss +73 -5
- package/select/styles/_index.scss +48 -9
- package/sidebar/styles/_index.scss +34 -2
- package/sparkline/styles/_index.scss +19 -0
- package/toolbar/styles/_index.scss +35 -1
- package/tree/styles/_index.scss +45 -6
- package/types/ngwr-bar-chart.d.ts +19 -1
- package/types/ngwr-calendar-heatmap.d.ts +29 -1
- package/types/ngwr-checkbox.d.ts +2 -0
- package/types/ngwr-date-picker.d.ts +308 -43
- package/types/ngwr-donut-chart.d.ts +24 -1
- package/types/ngwr-dropdown.d.ts +22 -2
- package/types/ngwr-event-calendar.d.ts +8 -0
- package/types/ngwr-form.d.ts +35 -5
- package/types/ngwr-gauge.d.ts +20 -1
- package/types/ngwr-input-number.d.ts +7 -0
- package/types/ngwr-line-chart.d.ts +9 -1
- package/types/ngwr-meter-group-testing.d.ts +3 -2
- package/types/ngwr-meter-group.d.ts +14 -1
- package/types/ngwr-page-header.d.ts +10 -2
- package/types/ngwr-popover.d.ts +154 -3
- package/types/ngwr-sidebar.d.ts +7 -0
- package/types/ngwr-sparkline.d.ts +43 -1
- package/types/ngwr-toolbar.d.ts +7 -0
- package/types/ngwr-version.d.ts +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngwr-i18n-zh.mjs","sources":["../../../projects/lib/i18n/zh/public-api.ts","../../../projects/lib/i18n/zh/ngwr-i18n-zh.ts"],"sourcesContent":["import { type WrI18nCatalog } from 'ngwr/i18n';\n\n/** Base Simplified Chinese catalog for ngwr built-in component strings. */\nexport const wrZh: WrI18nCatalog = {\n common: {\n ok: '确定',\n cancel: '取消',\n close: '关闭',\n confirm: '确认',\n delete: '删除',\n save: '保存',\n edit: '编辑',\n add: '添加',\n remove: '移除',\n clear: '清除',\n search: '搜索',\n loading: '加载中…',\n select: '选择',\n next: '下一步',\n previous: '上一步',\n back: '返回',\n today: '今天',\n yesterday: '昨天',\n tomorrow: '明天',\n of: '共',\n },\n pagination: {\n prev: '上一页',\n next: '下一页',\n itemsPerPage: '每页条数',\n perPage: '{{size}} 条/页',\n goToPage: '跳转到第 {{page}} 页',\n label: '分页',\n pageOf: '第 {{current}} 页,共 {{total}} 页',\n range: '{{from}}–{{to}},共 {{total}} 条',\n compact: '{{current}} / {{total}}',\n },\n table: {\n empty: '暂无数据',\n loading: '加载中…',\n sort: '对此列排序',\n filter: '筛选此列',\n selectAll: '选择所有行',\n selectRow: '选择行',\n expandRow: '展开或收起行详情',\n toggleRow: '展开或收起子行',\n selectGroup: '选择分组',\n toggleGroup: '展开或收起分组',\n noMatches: '无匹配结果',\n search: '搜索',\n reset: '重置',\n },\n eventCalendar: {\n today: '今天',\n previous: '上一个',\n next: '下一个',\n month: '月',\n week: '周',\n day: '日',\n time: '时间',\n allDay: '全天',\n label: '日历',\n more: '+{{count}} 项',\n header: '{{year}}年{{month}}',\n range: '{{from}} – {{to}}',\n chipLabel: '{{title}},{{time}}',\n slotLabel: '{{date}} {{time}}',\n allDayCellLabel: '{{date}} {{label}}',\n },\n tour: {\n next: '下一步',\n back: '上一步',\n done: '完成',\n skip: '跳过引导',\n progress: '第 {{current}} 步,共 {{total}} 步',\n },\n splitter: {\n divider: '调整面板大小',\n },\n stepper: {\n optional: '可选',\n },\n transfer: {\n source: '待选',\n target: '已选',\n search: '搜索',\n empty: '暂无内容',\n selectAll: '全选',\n toTarget: '移至已选',\n toSource: '移回待选',\n count: '{{checked}} / {{total}}',\n selectAllAria: '{{pane}} — {{action}}',\n },\n form: {\n optional: '选填',\n },\n validation: {\n required: '此项为必填项。',\n requiredTrue: '请勾选此项。',\n email: '请输入有效的电子邮箱地址。',\n minlength: '请至少输入 {{requiredLength}} 个字符。',\n maxlength: '最多可输入 {{requiredLength}} 个字符。',\n min: '请输入不小于 {{min}} 的值。',\n max: '请输入不大于 {{max}} 的值。',\n pattern: '此值的格式不正确。',\n noWhitespace: '此值不能包含空格。',\n hexColor: '请输入十六进制颜色值,例如 #1a2b3c。',\n url: '请输入有效的网址。',\n cardNumber: '请输入有效的卡号。',\n cvc: '请输入 {{length}} 位安全码。',\n iban: '请输入有效的 IBAN。',\n match: '两个值不一致。',\n matchFields: '这些字段的值不一致。',\n oneOf: '请从允许的值中选择。',\n minDate: '请选择更晚的日期。',\n maxDate: '请选择更早的日期。',\n },\n select: {\n label: '选择',\n placeholder: '请选择',\n empty: '暂无选项',\n clearSelection: '清除选择',\n removeItem: '移除 {{label}}',\n noResults: '无搜索结果',\n loading: '加载中…',\n more: '+{{count}} 项',\n },\n tree: {\n expand: '展开',\n collapse: '收起',\n placeholder: '请选择',\n clearSelection: '清除选择',\n removeItem: '移除 {{label}}',\n more: '+{{count}} 项',\n },\n commandPalette: {\n label: '命令面板',\n placeholder: '输入命令或搜索…',\n noResults: '无搜索结果',\n loading: '搜索中…',\n escHint: 'esc',\n },\n empty: {\n noData: '暂无数据',\n },\n fileUpload: {\n browse: '点击选择文件',\n dropZone: '或将文件拖放到此处',\n dropZoneLabel: '文件拖放区域,点击或拖放文件',\n removeFile: '移除文件',\n invalid: '不支持的文件类型',\n tooBig: '文件过大',\n size: '{{value}} {{unit}}',\n unitByte: 'B',\n unitKb: 'KB',\n unitMb: 'MB',\n unitGb: 'GB',\n unitTb: 'TB',\n },\n popconfirm: {\n label: '确认操作',\n confirm: '确认',\n cancel: '取消',\n },\n toast: {\n region: '通知',\n close: '关闭',\n copy: '复制',\n copied: '已复制',\n closeAll: '全部关闭',\n },\n input: {\n showPassword: '显示密码',\n hidePassword: '隐藏密码',\n },\n inputNumber: {\n increment: '增加',\n decrement: '减少',\n },\n inputOtp: {\n label: '验证码',\n digit: '第 {{index}} 位数字',\n character: '第 {{index}} 个字符',\n },\n anchor: {\n label: '目录',\n },\n avatar: {\n alt: '头像',\n },\n backTop: {\n label: '返回顶部',\n },\n breadcrumbs: {\n label: '面包屑导航',\n },\n burger: {\n label: '打开或关闭菜单',\n },\n calendar: {\n prevMonth: '上个月',\n nextMonth: '下个月',\n prevYear: '上一年',\n nextYear: '下一年',\n monthList: '月份',\n yearList: '年份',\n prevYears: '前 12 年',\n nextYears: '后 12 年',\n header: '{{year}}年{{month}}',\n yearRange: '{{from}} – {{to}}',\n dayLabel: '{{date}} {{weekday}}',\n },\n imageCropper: {\n empty: '暂无图片',\n window: '裁剪区域',\n keyHelp:\n '方向键移动裁剪框。按住 Alt 加方向键可调整大小,按住 Shift 可加大步长。' +\n '裁剪框会以图像像素为单位,依次朗读左、上、宽、高四个值。',\n },\n sortableList: {\n keyHelp: '按空格键拿起此项,然后用方向键移动。再次按空格键放下,或按 Esc 键放回原位。',\n grabbed: '已拿起。第 {{index}} 项,共 {{total}} 项。',\n moved: '第 {{index}} 项,共 {{total}} 项。',\n dropped: '已放下。第 {{index}} 项,共 {{total}} 项。',\n cancelled: '已取消移动。',\n },\n colorPicker: {\n area: '饱和度 {{saturation}}%,明度 {{brightness}}%',\n hue: '色相',\n alpha: '不透明度',\n formatHex: 'HEX',\n formatRgb: 'RGB',\n formatHsl: 'HSL',\n channelHex: 'HEX',\n channelRed: 'R',\n channelGreen: 'G',\n channelBlue: 'B',\n channelHue: 'H',\n channelSaturation: 'S%',\n channelLightness: 'L%',\n channelAlpha: 'A%',\n },\n calendarHeatmap: {\n label: '日历热力图',\n cell: '{{date}}: {{count}}',\n },\n lineChart: {\n label: '折线图',\n thousands: '{{value}}千',\n },\n donutChart: {\n label: '环形图',\n },\n compare: {\n label: '对比分隔条',\n },\n carousel: {\n label: '轮播图',\n goToSlide: '转到第 {{index}} 张幻灯片',\n prev: '上一张幻灯片',\n next: '下一张幻灯片',\n pagination: '轮播分页',\n roledescription: '轮播图',\n slideRoledescription: '幻灯片',\n },\n actionSheet: {\n label: '操作',\n },\n alert: {\n close: '关闭提示',\n },\n qr: {\n label: '二维码',\n },\n image: {\n viewer: '图片预览',\n open: '打开预览',\n close: '关闭预览',\n },\n window: {\n close: '关闭',\n minimize: '最小化',\n maximize: '最大化',\n restore: '还原',\n restoreDown: '向下还原',\n restoreWindow: '还原 {{title}}',\n closeWindow: '关闭窗口',\n untitled: '无标题',\n taskbar: '已最小化的窗口',\n },\n dialog: {\n close: '关闭对话框',\n },\n popover: {\n label: '弹出面板',\n },\n markdown: {\n copy: '复制代码',\n copied: '已复制',\n taskDone: '已完成:',\n taskTodo: '待办:',\n },\n marquee: {\n label: '跑马灯',\n link: '链接',\n },\n mention: {\n listbox: '提及',\n available: '匹配项:{{count}}',\n inserted: '已插入:{{label}}',\n },\n drawer: {\n close: '关闭抽屉',\n },\n datePicker: {\n open: '打开日历',\n openTime: '打开时间选择器',\n openDateTime: '打开日期时间选择器',\n openRange: '打开日期范围日历',\n panel: '选择日期',\n panelTime: '选择时间',\n panelDateTime: '选择日期和时间',\n panelRange: '选择日期范围',\n panelRangeDateTime: '选择日期和时间范围',\n rangeStart: '起始日期',\n rangeEnd: '结束日期',\n startTime: '开始时间',\n endTime: '结束时间',\n hours: '小时',\n minutes: '分钟',\n seconds: '秒',\n incrementHours: '增加小时',\n decrementHours: '减少小时',\n incrementMinutes: '增加分钟',\n decrementMinutes: '减少分钟',\n incrementSeconds: '增加秒',\n decrementSeconds: '减少秒',\n toggleAmPm: '切换上午/下午',\n am: '上午',\n pm: '下午',\n },\n sidebar: {\n label: '侧边栏',\n },\n spinner: {\n label: '加载中',\n },\n rating: {\n label: '评分',\n },\n gauge: {\n label: '仪表盘',\n },\n graph: {\n label: '图',\n parents: '父节点:{{names}}。',\n children: '子节点:{{names}}。',\n },\n progress: {\n label: '进度',\n },\n meterGroup: {\n label: '计量条',\n },\n knob: {\n label: '数值',\n },\n slider: {\n label: '数值',\n lower: '下限值',\n upper: '上限值',\n },\n speedDial: {\n label: '操作',\n },\n statistic: {\n delta: '{{value}}{{suffix}}',\n deltaSuffix: '%',\n },\n result: {\n notFound: '抱歉,您访问的页面不存在。',\n forbidden: '抱歉,您无权访问此页面。',\n serverError: '抱歉,出错了。',\n },\n date: {\n months: {\n jan: '一月',\n feb: '二月',\n mar: '三月',\n apr: '四月',\n may: '五月',\n jun: '六月',\n jul: '七月',\n aug: '八月',\n sep: '九月',\n oct: '十月',\n nov: '十一月',\n dec: '十二月',\n },\n },\n};\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ngwr-i18n-zh.mjs","sources":["../../../projects/lib/i18n/zh/public-api.ts","../../../projects/lib/i18n/zh/ngwr-i18n-zh.ts"],"sourcesContent":["import { type WrI18nCatalog } from 'ngwr/i18n';\n\n/** Base Simplified Chinese catalog for ngwr built-in component strings. */\nexport const wrZh: WrI18nCatalog = {\n common: {\n ok: '确定',\n cancel: '取消',\n close: '关闭',\n confirm: '确认',\n delete: '删除',\n save: '保存',\n edit: '编辑',\n add: '添加',\n remove: '移除',\n clear: '清除',\n search: '搜索',\n loading: '加载中…',\n select: '选择',\n next: '下一步',\n previous: '上一步',\n back: '返回',\n today: '今天',\n yesterday: '昨天',\n tomorrow: '明天',\n of: '共',\n },\n pagination: {\n prev: '上一页',\n next: '下一页',\n itemsPerPage: '每页条数',\n perPage: '{{size}} 条/页',\n goToPage: '跳转到第 {{page}} 页',\n label: '分页',\n pageOf: '第 {{current}} 页,共 {{total}} 页',\n range: '{{from}}–{{to}},共 {{total}} 条',\n compact: '{{current}} / {{total}}',\n },\n table: {\n empty: '暂无数据',\n loading: '加载中…',\n sort: '对此列排序',\n filter: '筛选此列',\n selectAll: '选择所有行',\n selectRow: '选择行',\n expandRow: '展开或收起行详情',\n toggleRow: '展开或收起子行',\n selectGroup: '选择分组',\n toggleGroup: '展开或收起分组',\n noMatches: '无匹配结果',\n search: '搜索',\n reset: '重置',\n },\n eventCalendar: {\n today: '今天',\n previous: '上一个',\n next: '下一个',\n month: '月',\n week: '周',\n day: '日',\n time: '时间',\n allDay: '全天',\n label: '日历',\n more: '+{{count}} 项',\n header: '{{year}}年{{month}}',\n range: '{{from}} – {{to}}',\n chipLabel: '{{title}},{{time}}',\n slotLabel: '{{date}} {{time}}',\n allDayCellLabel: '{{date}} {{label}}',\n },\n tour: {\n next: '下一步',\n back: '上一步',\n done: '完成',\n skip: '跳过引导',\n progress: '第 {{current}} 步,共 {{total}} 步',\n },\n splitter: {\n divider: '调整面板大小',\n },\n stepper: {\n optional: '可选',\n },\n transfer: {\n source: '待选',\n target: '已选',\n search: '搜索',\n empty: '暂无内容',\n selectAll: '全选',\n toTarget: '移至已选',\n toSource: '移回待选',\n count: '{{checked}} / {{total}}',\n selectAllAria: '{{pane}} — {{action}}',\n },\n form: {\n optional: '选填',\n },\n validation: {\n required: '此项为必填项。',\n requiredTrue: '请勾选此项。',\n email: '请输入有效的电子邮箱地址。',\n minlength: '请至少输入 {{requiredLength}} 个字符。',\n maxlength: '最多可输入 {{requiredLength}} 个字符。',\n min: '请输入不小于 {{min}} 的值。',\n max: '请输入不大于 {{max}} 的值。',\n pattern: '此值的格式不正确。',\n noWhitespace: '此值不能包含空格。',\n hexColor: '请输入十六进制颜色值,例如 #1a2b3c。',\n url: '请输入有效的网址。',\n cardNumber: '请输入有效的卡号。',\n cvc: '请输入 {{length}} 位安全码。',\n iban: '请输入有效的 IBAN。',\n match: '两个值不一致。',\n matchFields: '这些字段的值不一致。',\n oneOf: '请从允许的值中选择。',\n minDate: '请选择更晚的日期。',\n maxDate: '请选择更早的日期。',\n dateFormat: '格式应为:{{example}}',\n dateFilter: '此日期不可选。',\n },\n select: {\n label: '选择',\n placeholder: '请选择',\n empty: '暂无选项',\n clearSelection: '清除选择',\n removeItem: '移除 {{label}}',\n noResults: '无搜索结果',\n loading: '加载中…',\n more: '+{{count}} 项',\n },\n tree: {\n expand: '展开',\n collapse: '收起',\n placeholder: '请选择',\n clearSelection: '清除选择',\n removeItem: '移除 {{label}}',\n more: '+{{count}} 项',\n },\n commandPalette: {\n label: '命令面板',\n placeholder: '输入命令或搜索…',\n noResults: '无搜索结果',\n loading: '搜索中…',\n escHint: 'esc',\n },\n empty: {\n noData: '暂无数据',\n },\n fileUpload: {\n browse: '点击选择文件',\n dropZone: '或将文件拖放到此处',\n dropZoneLabel: '文件拖放区域,点击或拖放文件',\n removeFile: '移除文件',\n invalid: '不支持的文件类型',\n tooBig: '文件过大',\n size: '{{value}} {{unit}}',\n unitByte: 'B',\n unitKb: 'KB',\n unitMb: 'MB',\n unitGb: 'GB',\n unitTb: 'TB',\n },\n popconfirm: {\n label: '确认操作',\n confirm: '确认',\n cancel: '取消',\n },\n toast: {\n region: '通知',\n close: '关闭',\n copy: '复制',\n copied: '已复制',\n closeAll: '全部关闭',\n },\n input: {\n showPassword: '显示密码',\n hidePassword: '隐藏密码',\n },\n inputNumber: {\n increment: '增加',\n decrement: '减少',\n },\n inputOtp: {\n label: '验证码',\n digit: '第 {{index}} 位数字',\n character: '第 {{index}} 个字符',\n },\n anchor: {\n label: '目录',\n },\n avatar: {\n alt: '头像',\n },\n backTop: {\n label: '返回顶部',\n },\n breadcrumbs: {\n label: '面包屑导航',\n },\n burger: {\n label: '打开或关闭菜单',\n },\n calendar: {\n prevMonth: '上个月',\n nextMonth: '下个月',\n prevYear: '上一年',\n nextYear: '下一年',\n monthList: '月份',\n yearList: '年份',\n prevYears: '前 12 年',\n nextYears: '后 12 年',\n header: '{{year}}年{{month}}',\n yearRange: '{{from}} – {{to}}',\n dayLabel: '{{date}} {{weekday}}',\n },\n imageCropper: {\n empty: '暂无图片',\n window: '裁剪区域',\n keyHelp:\n '方向键移动裁剪框。按住 Alt 加方向键可调整大小,按住 Shift 可加大步长。' +\n '裁剪框会以图像像素为单位,依次朗读左、上、宽、高四个值。',\n },\n sortableList: {\n keyHelp: '按空格键拿起此项,然后用方向键移动。再次按空格键放下,或按 Esc 键放回原位。',\n grabbed: '已拿起。第 {{index}} 项,共 {{total}} 项。',\n moved: '第 {{index}} 项,共 {{total}} 项。',\n dropped: '已放下。第 {{index}} 项,共 {{total}} 项。',\n cancelled: '已取消移动。',\n },\n colorPicker: {\n area: '饱和度 {{saturation}}%,明度 {{brightness}}%',\n hue: '色相',\n alpha: '不透明度',\n formatHex: 'HEX',\n formatRgb: 'RGB',\n formatHsl: 'HSL',\n channelHex: 'HEX',\n channelRed: 'R',\n channelGreen: 'G',\n channelBlue: 'B',\n channelHue: 'H',\n channelSaturation: 'S%',\n channelLightness: 'L%',\n channelAlpha: 'A%',\n },\n calendarHeatmap: {\n label: '日历热力图',\n cell: '{{date}}: {{count}}',\n },\n lineChart: {\n label: '折线图',\n thousands: '{{value}}千',\n },\n donutChart: {\n label: '环形图',\n },\n compare: {\n label: '对比分隔条',\n },\n carousel: {\n label: '轮播图',\n goToSlide: '转到第 {{index}} 张幻灯片',\n prev: '上一张幻灯片',\n next: '下一张幻灯片',\n pagination: '轮播分页',\n roledescription: '轮播图',\n slideRoledescription: '幻灯片',\n },\n actionSheet: {\n label: '操作',\n },\n alert: {\n close: '关闭提示',\n },\n qr: {\n label: '二维码',\n },\n image: {\n viewer: '图片预览',\n open: '打开预览',\n close: '关闭预览',\n },\n window: {\n close: '关闭',\n minimize: '最小化',\n maximize: '最大化',\n restore: '还原',\n restoreDown: '向下还原',\n restoreWindow: '还原 {{title}}',\n closeWindow: '关闭窗口',\n untitled: '无标题',\n taskbar: '已最小化的窗口',\n },\n dialog: {\n close: '关闭对话框',\n },\n popover: {\n label: '弹出面板',\n },\n markdown: {\n copy: '复制代码',\n copied: '已复制',\n taskDone: '已完成:',\n taskTodo: '待办:',\n },\n marquee: {\n label: '跑马灯',\n link: '链接',\n },\n mention: {\n listbox: '提及',\n available: '匹配项:{{count}}',\n inserted: '已插入:{{label}}',\n },\n drawer: {\n close: '关闭抽屉',\n },\n datePicker: {\n open: '打开日历',\n openTime: '打开时间选择器',\n openDateTime: '打开日期时间选择器',\n openRange: '打开日期范围日历',\n panel: '选择日期',\n panelTime: '选择时间',\n panelDateTime: '选择日期和时间',\n panelRange: '选择日期范围',\n panelRangeDateTime: '选择日期和时间范围',\n rangeStart: '起始日期',\n rangeEnd: '结束日期',\n startTime: '开始时间',\n endTime: '结束时间',\n hours: '小时',\n minutes: '分钟',\n seconds: '秒',\n incrementHours: '增加小时',\n decrementHours: '减少小时',\n incrementMinutes: '增加分钟',\n decrementMinutes: '减少分钟',\n incrementSeconds: '增加秒',\n decrementSeconds: '减少秒',\n toggleAmPm: '切换上午/下午',\n am: '上午',\n pm: '下午',\n },\n sidebar: {\n label: '侧边栏',\n },\n spinner: {\n label: '加载中',\n },\n rating: {\n label: '评分',\n },\n gauge: {\n label: '仪表盘',\n },\n graph: {\n label: '图',\n parents: '父节点:{{names}}。',\n children: '子节点:{{names}}。',\n },\n progress: {\n label: '进度',\n },\n meterGroup: {\n label: '计量条',\n },\n knob: {\n label: '数值',\n },\n slider: {\n label: '数值',\n lower: '下限值',\n upper: '上限值',\n },\n speedDial: {\n label: '操作',\n },\n statistic: {\n delta: '{{value}}{{suffix}}',\n deltaSuffix: '%',\n },\n result: {\n notFound: '抱歉,您访问的页面不存在。',\n forbidden: '抱歉,您无权访问此页面。',\n serverError: '抱歉,出错了。',\n },\n date: {\n months: {\n jan: '一月',\n feb: '二月',\n mar: '三月',\n apr: '四月',\n may: '五月',\n jun: '六月',\n jul: '七月',\n aug: '八月',\n sep: '九月',\n oct: '十月',\n nov: '十一月',\n dec: '十二月',\n },\n },\n};\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -174,8 +174,20 @@ class WrInputNumber {
|
|
|
174
174
|
return v !== null && v >= this.maxValue();
|
|
175
175
|
}, /* @ts-ignore */
|
|
176
176
|
...(ngDevMode ? [{ debugName: "atMax" }] : /* istanbul ignore next */ []));
|
|
177
|
+
/**
|
|
178
|
+
* The size and pill modifiers mirror what is bound down to the chrome, because
|
|
179
|
+
* the stepper column belongs to neither half of it: the field carries
|
|
180
|
+
* `wr-input--<size>`, the column is its SIBLING, and the group carries no size
|
|
181
|
+
* at all. Without a modifier of its own the column drew one 10x6 chevron at
|
|
182
|
+
* every size and ran its dividers into a pill's rounded end.
|
|
183
|
+
*/
|
|
177
184
|
classes = computed(() => {
|
|
178
185
|
const parts = ['wr-input-number'];
|
|
186
|
+
const size = this.resolvedSize();
|
|
187
|
+
if (size !== 'md')
|
|
188
|
+
parts.push(`wr-input-number--${size}`);
|
|
189
|
+
if (this.resolvedRounded())
|
|
190
|
+
parts.push('wr-input-number--rounded');
|
|
179
191
|
if (this.disabled())
|
|
180
192
|
parts.push('wr-input-number--disabled');
|
|
181
193
|
return parts.join(' ');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngwr-input-number.mjs","sources":["../../../projects/lib/input-number/input-number.ts","../../../projects/lib/input-number/input-number.html","../../../projects/lib/input-number/ngwr-input-number.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { type BooleanInput, coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';\nimport {\n Component,\n LOCALE_ID,\n ViewEncapsulation,\n computed,\n effect,\n inject,\n input,\n model,\n output,\n signal,\n} from '@angular/core';\nimport type { FormValueControl } from '@angular/forms/signals';\n\nimport { useConfigValue } from 'ngwr/config';\nimport { useI18nText } from 'ngwr/i18n';\nimport { WrInput, WrInputGroup, WrInputPrefix, WrInputSuffix, type WrInputSize } from 'ngwr/input';\nimport { clamp, round } from 'ngwr/utils';\n\n/** Round to `decimals` places, avoiding common float artefacts (`1.005 → 1.01`). */\n\n/** Resolve the locale's decimal + grouping separators from `Intl.NumberFormat`. */\nfunction resolveSeparators(locale: string): { decimal: string; group: string } {\n const parts = new Intl.NumberFormat(locale).formatToParts(12345.6);\n const decimal = parts.find(p => p.type === 'decimal')?.value ?? '.';\n const group = parts.find(p => p.type === 'group')?.value ?? '';\n return { decimal, group };\n}\n\n/**\n * Numeric input with locale-aware formatting + ▲▼ stepper buttons.\n *\n * A signal-forms native control: it implements `FormValueControl<number | null>`,\n * so `[formField]` binds straight to its `value` model — no\n * `ControlValueAccessor` in between. `[(value)]` works standalone.\n *\n * Parses leniently while typing (allows partial input like `\"1.\"` or `\"-\"`),\n * re-formats with grouping + fixed decimals on blur.\n *\n * Locale comes from Angular's `LOCALE_ID` — input-number intentionally does\n * NOT depend on `ngwr/date` so it can be used in date-free apps.\n *\n * @example\n * ```html\n * <!-- signal forms -->\n * <wr-input-number [formField]=\"form.qty\" [min]=\"0\" [max]=\"100\" />\n *\n * <!-- standalone two-way binding -->\n * <wr-input-number [(value)]=\"price\" [decimals]=\"2\" suffix=\"USD\" />\n * ```\n *\n * @see https://ngwr.dev/reference/components/input-number\n */\n@Component({\n selector: 'wr-input-number',\n templateUrl: './input-number.html',\n encapsulation: ViewEncapsulation.None,\n host: { '[class]': 'classes()' },\n imports: [WrInput, WrInputGroup, WrInputPrefix, WrInputSuffix],\n})\nexport class WrInputNumber implements FormValueControl<number | null> {\n /** Minimum allowed value. @default -Infinity */\n readonly min = input<number | undefined>(Number.NEGATIVE_INFINITY, {\n transform: (v: unknown): number => coerceNumberProperty(v, Number.NEGATIVE_INFINITY),\n });\n\n /** Maximum allowed value. @default Infinity */\n readonly max = input<number | undefined>(Number.POSITIVE_INFINITY, {\n transform: (v: unknown): number => coerceNumberProperty(v, Number.POSITIVE_INFINITY),\n });\n\n private readonly minValue = computed(() => this.min() ?? Number.NEGATIVE_INFINITY);\n private readonly maxValue = computed(() => this.max() ?? Number.POSITIVE_INFINITY);\n\n /** Step used by stepper buttons + arrow keys. @default 1 */\n readonly step = input(1, { transform: (v: unknown): number => Math.max(0, coerceNumberProperty(v, 1)) });\n\n /**\n * Fixed number of decimals shown on blur. `null` keeps the entered precision.\n *\n * Clamped to what `toFixed` accepts — 0 to 100 — because it is the one numeric\n * input on this component that had no transform, and the value goes straight\n * into `toFixed`, which THROWS a `RangeError` outside that range rather than\n * degrading. A `[decimals]=\"-1\"` bound from a config object took the whole\n * component down on blur.\n *\n * @default null\n */\n readonly decimals = input<number | null, unknown>(null, {\n transform: (v: unknown): number | null =>\n v === null || v === undefined ? null : Math.min(100, Math.max(0, Math.trunc(coerceNumberProperty(v, 0)))),\n });\n\n /** Render the ▲▼ stepper column. @default true */\n readonly showSteppers = input(true, { transform: coerceBooleanProperty });\n\n /**\n * Control size — forwarded to the field, and shares the `--wr-control-*`\n * contract. Unset falls back to the `inputNumber.size` app default from\n * `provideWrConfig()`, then to the `input.size` one, then to `md`. @default 'md'\n */\n readonly size = input<WrInputSize | null>(null);\n\n /**\n * Pill-shaped corners. Unset falls back to the `inputNumber.rounded` app default\n * from `provideWrConfig()`, then to the `input.rounded` one;\n * `[rounded]=\"false\"` turns a configured `true` back off. @default false\n */\n readonly rounded = input<boolean | null, BooleanInput>(null, {\n // Null-preserving: the plain `coerceBooleanProperty` folds `null` into\n // `false`, which would make \"not set\" and \"set to false\" the same value —\n // and a config default nothing could ever supply.\n transform: (v: BooleanInput): boolean | null => (v == null ? null : coerceBooleanProperty(v)),\n });\n\n /**\n * `size`, then the app config, then `md` — bound to the field's `[size]`.\n *\n * The chrome this control is built from resolves the same pair for itself, so\n * the config lookup falls through to `input.*` rather than stopping at\n * `inputNumber.*`: binding a value down always wins there, and an unchained\n * lookup would therefore SUPPRESS an `input.size` an app had set — the field\n * inside a number input would be the one `[wrInput]` in the app that ignored it.\n * Chained, the specific key wins where it is set and the general one still\n * applies where it is not.\n */\n protected readonly resolvedSize = useConfigValue(this.size, c => c.inputNumber?.size ?? c.input?.size, 'md');\n\n /** `rounded`, then the app config, then `false` — bound to the group AND the field. */\n protected readonly resolvedRounded = useConfigValue(\n this.rounded,\n c => c.inputNumber?.rounded ?? c.input?.rounded,\n false\n );\n\n /** Optional prefix label (e.g. `\"$\"`). */\n readonly prefix = input<string>('');\n\n /** Optional suffix label (e.g. `\"kg\"`). */\n readonly suffix = input<string>('');\n\n /** Placeholder shown when the input is empty. */\n readonly placeholder = input<string>('');\n\n /**\n * Accessible name for the field. Unset, the field is named by whatever labels\n * it — there is deliberately no fallback here.\n *\n * It used to mirror the `placeholder`, and an `aria-label` OUTRANKS a\n * `<label>` in the accname order: inside a `<wr-form-field label=\"Quantity\">`\n * the very input that adopts the field's id announced the placeholder (\"0\")\n * instead, and a placeholder disappears as soon as the user types. Standalone\n * nothing was lost by dropping it — an input with no other name already falls\n * back to its own `placeholder` attribute, which is the name axe's `label`\n * rule accepts too.\n */\n readonly ariaLabel = input<string | null>(null);\n\n protected readonly resolvedAriaLabel = computed(() => {\n // Not `??`: an empty binding is no name at all, and an empty `aria-label` is\n // worse than none — it still wins the accname order, and announces nothing.\n const explicit = this.ariaLabel();\n if (explicit) return explicit;\n return null;\n });\n\n /** Increment button aria-label. Falls back to `inputNumber.increment`. */\n readonly incrementLabel = input<string | null>(null);\n\n /** Decrement button aria-label. Falls back to `inputNumber.decrement`. */\n readonly decrementLabel = input<string | null>(null);\n\n /**\n * The steppers are icon-only buttons, so these ARE their accessible names.\n * They were hard-coded English while the catalog carried the keys for them\n * unread — a Russian app announced \"Increment\".\n */\n protected readonly resolvedIncrement = useI18nText(this.incrementLabel, 'inputNumber.increment', 'Increment');\n protected readonly resolvedDecrement = useI18nText(this.decrementLabel, 'inputNumber.decrement', 'Decrement');\n\n /** Disable interaction. @default false */\n readonly disabled = input(false, { transform: coerceBooleanProperty });\n\n /** Read-only — values cannot be changed (steppers + typing disabled). @default false */\n readonly readonly = input(false, { transform: coerceBooleanProperty });\n\n /** Numeric value (`null` when empty). Bound by `[formField]`, or two-way via `[(value)]`. */\n readonly value = model<number | null>(null);\n\n /** Emitted on blur so a bound field can mark itself touched. */\n readonly touch = output<void>();\n\n private readonly locale = inject(LOCALE_ID);\n private readonly separators = resolveSeparators(this.locale);\n\n /** Text currently in the input (may be partial / invalid mid-type). */\n protected readonly text = signal<string>('');\n\n /** Whether the input is focused. While true, the input handlers own `text`. */\n protected readonly focused = signal(false);\n\n protected readonly interactive = computed(() => !this.disabled() && !this.readonly());\n\n protected readonly atMin = computed(() => {\n const v = this.value();\n return v !== null && v <= this.minValue();\n });\n\n protected readonly atMax = computed(() => {\n const v = this.value();\n return v !== null && v >= this.maxValue();\n });\n\n protected readonly classes = computed(() => {\n const parts = ['wr-input-number'];\n if (this.disabled()) parts.push('wr-input-number--disabled');\n return parts.join(' ');\n });\n\n /**\n * Fraction digits the stepper rounds its arithmetic to when `decimals` says\n * nothing. High enough to leave a real value alone, low enough to erase the\n * binary-float tail that repeated stepping accumulates.\n */\n private static readonly STEP_PRECISION = 10;\n\n /**\n * Above this, the anti-drift round is skipped — it would MANUFACTURE drift.\n *\n * `round(v, 10)` is `Math.round((v + EPSILON) * 1e10) / 1e10`, and the scale\n * factor is only exact while `v * 1e10` stays inside 2^53, i.e. |v| under\n * about 900,720. In practice the round-trip still recovers up to ~9.2e8 and\n * then breaks: `round(1000000001, 10)` is `1000000000.9999999`, and since\n * `format` prints up to 20 fraction digits that tail reaches the screen —\n * and compounds, because the next press starts from it. Integer stepping at\n * that magnitude is exact in IEEE754 and needed no help; the only thing this\n * rounding exists to defend is `0.1 + 0.1 + 0.1`.\n */\n private static readonly SAFE_ROUND_MAGNITUDE = 1e6;\n\n /** Steps finer than this would be rounded away by {@link STEP_PRECISION}. */\n private static readonly SAFE_ROUND_STEP = 1e-9;\n\n constructor() {\n // Keep the display `text` in sync with external writes to `value` (via\n // `[formField]` / `[(value)]`). While the user is editing, the input\n // handlers own `text`, so skip re-formatting to avoid clobbering partial\n // input (e.g. mid-typed grouping or a value that is still being clamped).\n effect(() => {\n const v = this.value();\n if (this.focused()) return;\n if (v === null || Number.isNaN(v)) {\n this.text.set('');\n return;\n }\n // SHOW WHAT THE MODEL HOLDS. It used to format `constrain(v)`, so a\n // `[max]=\"10\"` field handed 500 drew \"10\" over a model that still said\n // 500 — the display was the thing lying, not the model.\n //\n // The tempting repair is to write the clamp back so the two agree, and\n // that is worse: under `[formField]` the bounds arrive ONLY through the\n // schema's `min()` / `max()` rules (binding `[min]` next to `[formField]`\n // is an NG8022 compile error), so overwriting the value ERASES the very\n // error those rules exist to raise — and the write marks a pristine form\n // dirty, tripping unsaved-changes guards and opening every other\n // validator's message on first paint.\n //\n // So: `min` / `max` bound what this component's own edits may produce,\n // and a value written from outside is displayed as it is and left for\n // validation to judge.\n this.text.set(this.format(v));\n });\n }\n\n // Template handlers\n\n protected onInput(event: Event): void {\n const raw = (event.target as HTMLInputElement).value;\n this.text.set(raw);\n if (!raw.trim()) {\n this.value.set(null);\n return;\n }\n const parsed = this.parse(raw);\n if (parsed === null) return; // partial input — wait for more\n const next = this.constrain(parsed);\n this.value.set(next);\n }\n\n protected onFocus(): void {\n this.focused.set(true);\n }\n\n protected onBlur(): void {\n // Flipping `focused` false lets the sync effect re-format `text` from the\n // committed `value` (e.g. `\"1.\"` → `\"1\"`, or grouping the final number).\n this.focused.set(false);\n this.touch.emit();\n }\n\n protected onKeydown(event: KeyboardEvent): void {\n if (!this.interactive()) return;\n if (event.key !== 'ArrowUp' && event.key !== 'ArrowDown') return;\n event.preventDefault();\n const direction = event.key === 'ArrowUp' ? 1 : -1;\n const multiplier = event.shiftKey ? 10 : 1;\n this.bump(direction * multiplier);\n }\n\n protected stepBy(direction: 1 | -1): void {\n if (!this.interactive()) return;\n this.bump(direction);\n }\n\n // Internals\n\n private bump(units: number): void {\n const stepSize = this.step() || 1;\n const base = this.value() ?? this.fallbackBase();\n // `round` before `constrain`, and only on the stepped ARITHMETIC. Binary\n // floats do not add: three presses of a `step=\"0.1\"` stepper produced\n // 0.30000000000000004, `constrain` only rounds when `decimals` is set, and\n // `format` prints up to 20 fraction digits — so the drift went into the\n // model AND onto the screen. Ten digits erases IEEE noise without\n // quantising a value the user typed (0.15000000000000002 stays 0.15, it\n // does not snap to the step grid).\n //\n // Guarded on BOTH ends, because outside them the correction is the thing\n // that corrupts: see SAFE_ROUND_MAGNITUDE, and a step finer than 1e-9 would\n // simply be rounded away to nothing.\n const raw = base + units * stepSize;\n const correctable =\n Math.abs(raw) < WrInputNumber.SAFE_ROUND_MAGNITUDE && Math.abs(stepSize) >= WrInputNumber.SAFE_ROUND_STEP;\n const next = this.constrain(correctable ? round(raw, WrInputNumber.STEP_PRECISION) : raw);\n this.value.set(next);\n this.text.set(this.format(next));\n }\n\n /** Choose a sensible starting point when bumping from `null`. */\n private fallbackBase(): number {\n if (Number.isFinite(this.minValue()) && this.minValue() > 0) return this.minValue();\n if (Number.isFinite(this.maxValue()) && this.maxValue() < 0) return this.maxValue();\n return 0;\n }\n\n private constrain(v: number): number {\n let next = clamp(v, this.minValue(), this.maxValue());\n const d = this.decimals();\n if (d !== null) next = round(next, d);\n return next;\n }\n\n /** Parse a locale-formatted string. Returns `null` for partial / not-yet-numeric input. */\n private parse(raw: string): number | null {\n const trimmed = raw.trim();\n if (!trimmed) return null;\n // Strip group separators, normalise the decimal separator to `.`.\n let normalised = trimmed;\n if (this.separators.group) {\n normalised = normalised.split(this.separators.group).join('');\n }\n if (this.separators.decimal !== '.') {\n normalised = normalised.split(this.separators.decimal).join('.');\n }\n // Partial inputs we don't want to clobber while the user is still typing:\n // `-`, `-.`, `.`, `1.`, `-1.` etc.\n if (/^-?\\.?$/.test(normalised) || normalised.endsWith('.')) return null;\n const n = Number(normalised);\n return Number.isFinite(n) ? n : null;\n }\n\n /** Format a value using `Intl.NumberFormat` for the active locale. */\n private format(v: number): string {\n const d = this.decimals();\n const formatter = new Intl.NumberFormat(this.locale, {\n minimumFractionDigits: d ?? 0,\n maximumFractionDigits: d ?? 20,\n useGrouping: true,\n });\n return formatter.format(v);\n }\n}\n","<wr-input-group [rounded]=\"resolvedRounded()\">\n @if (prefix(); as p) {\n <span wrInputPrefix>{{ p }}</span>\n }\n <input\n #input\n wrInput\n type=\"text\"\n inputmode=\"decimal\"\n autocomplete=\"off\"\n [size]=\"resolvedSize()\"\n [rounded]=\"resolvedRounded()\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\n spellcheck=\"false\"\n [value]=\"text()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n (input)=\"onInput($event)\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n (keydown)=\"onKeydown($event)\"\n />\n @if (suffix(); as s) {\n <span wrInputSuffix>{{ s }}</span>\n }\n @if (showSteppers()) {\n <div class=\"wr-input-number__steppers\" wrInputSuffix>\n <button\n type=\"button\"\n class=\"wr-input-number__step\"\n tabindex=\"-1\"\n [attr.aria-label]=\"resolvedIncrement()\"\n [disabled]=\"!interactive() || atMax()\"\n (click)=\"stepBy(1)\"\n >\n <svg width=\"10\" height=\"6\" viewBox=\"0 0 8 5\" aria-hidden=\"true\">\n <path d=\"M0 5 L4 0 L8 5 Z\" fill=\"currentColor\" />\n </svg>\n </button>\n <button\n type=\"button\"\n class=\"wr-input-number__step\"\n tabindex=\"-1\"\n [attr.aria-label]=\"resolvedDecrement()\"\n [disabled]=\"!interactive() || atMin()\"\n (click)=\"stepBy(-1)\"\n >\n <svg width=\"10\" height=\"6\" viewBox=\"0 0 8 5\" aria-hidden=\"true\">\n <path d=\"M0 0 L4 5 L8 0 Z\" fill=\"currentColor\" />\n </svg>\n </button>\n </div>\n }\n</wr-input-group>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ngwr-input-number.mjs","sources":["../../../projects/lib/input-number/input-number.ts","../../../projects/lib/input-number/input-number.html","../../../projects/lib/input-number/ngwr-input-number.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { type BooleanInput, coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';\nimport {\n Component,\n LOCALE_ID,\n ViewEncapsulation,\n computed,\n effect,\n inject,\n input,\n model,\n output,\n signal,\n} from '@angular/core';\nimport type { FormValueControl } from '@angular/forms/signals';\n\nimport { useConfigValue } from 'ngwr/config';\nimport { useI18nText } from 'ngwr/i18n';\nimport { WrInput, WrInputGroup, WrInputPrefix, WrInputSuffix, type WrInputSize } from 'ngwr/input';\nimport { clamp, round } from 'ngwr/utils';\n\n/** Round to `decimals` places, avoiding common float artefacts (`1.005 → 1.01`). */\n\n/** Resolve the locale's decimal + grouping separators from `Intl.NumberFormat`. */\nfunction resolveSeparators(locale: string): { decimal: string; group: string } {\n const parts = new Intl.NumberFormat(locale).formatToParts(12345.6);\n const decimal = parts.find(p => p.type === 'decimal')?.value ?? '.';\n const group = parts.find(p => p.type === 'group')?.value ?? '';\n return { decimal, group };\n}\n\n/**\n * Numeric input with locale-aware formatting + ▲▼ stepper buttons.\n *\n * A signal-forms native control: it implements `FormValueControl<number | null>`,\n * so `[formField]` binds straight to its `value` model — no\n * `ControlValueAccessor` in between. `[(value)]` works standalone.\n *\n * Parses leniently while typing (allows partial input like `\"1.\"` or `\"-\"`),\n * re-formats with grouping + fixed decimals on blur.\n *\n * Locale comes from Angular's `LOCALE_ID` — input-number intentionally does\n * NOT depend on `ngwr/date` so it can be used in date-free apps.\n *\n * @example\n * ```html\n * <!-- signal forms -->\n * <wr-input-number [formField]=\"form.qty\" [min]=\"0\" [max]=\"100\" />\n *\n * <!-- standalone two-way binding -->\n * <wr-input-number [(value)]=\"price\" [decimals]=\"2\" suffix=\"USD\" />\n * ```\n *\n * @see https://ngwr.dev/reference/components/input-number\n */\n@Component({\n selector: 'wr-input-number',\n templateUrl: './input-number.html',\n encapsulation: ViewEncapsulation.None,\n host: { '[class]': 'classes()' },\n imports: [WrInput, WrInputGroup, WrInputPrefix, WrInputSuffix],\n})\nexport class WrInputNumber implements FormValueControl<number | null> {\n /** Minimum allowed value. @default -Infinity */\n readonly min = input<number | undefined>(Number.NEGATIVE_INFINITY, {\n transform: (v: unknown): number => coerceNumberProperty(v, Number.NEGATIVE_INFINITY),\n });\n\n /** Maximum allowed value. @default Infinity */\n readonly max = input<number | undefined>(Number.POSITIVE_INFINITY, {\n transform: (v: unknown): number => coerceNumberProperty(v, Number.POSITIVE_INFINITY),\n });\n\n private readonly minValue = computed(() => this.min() ?? Number.NEGATIVE_INFINITY);\n private readonly maxValue = computed(() => this.max() ?? Number.POSITIVE_INFINITY);\n\n /** Step used by stepper buttons + arrow keys. @default 1 */\n readonly step = input(1, { transform: (v: unknown): number => Math.max(0, coerceNumberProperty(v, 1)) });\n\n /**\n * Fixed number of decimals shown on blur. `null` keeps the entered precision.\n *\n * Clamped to what `toFixed` accepts — 0 to 100 — because it is the one numeric\n * input on this component that had no transform, and the value goes straight\n * into `toFixed`, which THROWS a `RangeError` outside that range rather than\n * degrading. A `[decimals]=\"-1\"` bound from a config object took the whole\n * component down on blur.\n *\n * @default null\n */\n readonly decimals = input<number | null, unknown>(null, {\n transform: (v: unknown): number | null =>\n v === null || v === undefined ? null : Math.min(100, Math.max(0, Math.trunc(coerceNumberProperty(v, 0)))),\n });\n\n /** Render the ▲▼ stepper column. @default true */\n readonly showSteppers = input(true, { transform: coerceBooleanProperty });\n\n /**\n * Control size — forwarded to the field, and shares the `--wr-control-*`\n * contract. Unset falls back to the `inputNumber.size` app default from\n * `provideWrConfig()`, then to the `input.size` one, then to `md`. @default 'md'\n */\n readonly size = input<WrInputSize | null>(null);\n\n /**\n * Pill-shaped corners. Unset falls back to the `inputNumber.rounded` app default\n * from `provideWrConfig()`, then to the `input.rounded` one;\n * `[rounded]=\"false\"` turns a configured `true` back off. @default false\n */\n readonly rounded = input<boolean | null, BooleanInput>(null, {\n // Null-preserving: the plain `coerceBooleanProperty` folds `null` into\n // `false`, which would make \"not set\" and \"set to false\" the same value —\n // and a config default nothing could ever supply.\n transform: (v: BooleanInput): boolean | null => (v == null ? null : coerceBooleanProperty(v)),\n });\n\n /**\n * `size`, then the app config, then `md` — bound to the field's `[size]`.\n *\n * The chrome this control is built from resolves the same pair for itself, so\n * the config lookup falls through to `input.*` rather than stopping at\n * `inputNumber.*`: binding a value down always wins there, and an unchained\n * lookup would therefore SUPPRESS an `input.size` an app had set — the field\n * inside a number input would be the one `[wrInput]` in the app that ignored it.\n * Chained, the specific key wins where it is set and the general one still\n * applies where it is not.\n */\n protected readonly resolvedSize = useConfigValue(this.size, c => c.inputNumber?.size ?? c.input?.size, 'md');\n\n /** `rounded`, then the app config, then `false` — bound to the group AND the field. */\n protected readonly resolvedRounded = useConfigValue(\n this.rounded,\n c => c.inputNumber?.rounded ?? c.input?.rounded,\n false\n );\n\n /** Optional prefix label (e.g. `\"$\"`). */\n readonly prefix = input<string>('');\n\n /** Optional suffix label (e.g. `\"kg\"`). */\n readonly suffix = input<string>('');\n\n /** Placeholder shown when the input is empty. */\n readonly placeholder = input<string>('');\n\n /**\n * Accessible name for the field. Unset, the field is named by whatever labels\n * it — there is deliberately no fallback here.\n *\n * It used to mirror the `placeholder`, and an `aria-label` OUTRANKS a\n * `<label>` in the accname order: inside a `<wr-form-field label=\"Quantity\">`\n * the very input that adopts the field's id announced the placeholder (\"0\")\n * instead, and a placeholder disappears as soon as the user types. Standalone\n * nothing was lost by dropping it — an input with no other name already falls\n * back to its own `placeholder` attribute, which is the name axe's `label`\n * rule accepts too.\n */\n readonly ariaLabel = input<string | null>(null);\n\n protected readonly resolvedAriaLabel = computed(() => {\n // Not `??`: an empty binding is no name at all, and an empty `aria-label` is\n // worse than none — it still wins the accname order, and announces nothing.\n const explicit = this.ariaLabel();\n if (explicit) return explicit;\n return null;\n });\n\n /** Increment button aria-label. Falls back to `inputNumber.increment`. */\n readonly incrementLabel = input<string | null>(null);\n\n /** Decrement button aria-label. Falls back to `inputNumber.decrement`. */\n readonly decrementLabel = input<string | null>(null);\n\n /**\n * The steppers are icon-only buttons, so these ARE their accessible names.\n * They were hard-coded English while the catalog carried the keys for them\n * unread — a Russian app announced \"Increment\".\n */\n protected readonly resolvedIncrement = useI18nText(this.incrementLabel, 'inputNumber.increment', 'Increment');\n protected readonly resolvedDecrement = useI18nText(this.decrementLabel, 'inputNumber.decrement', 'Decrement');\n\n /** Disable interaction. @default false */\n readonly disabled = input(false, { transform: coerceBooleanProperty });\n\n /** Read-only — values cannot be changed (steppers + typing disabled). @default false */\n readonly readonly = input(false, { transform: coerceBooleanProperty });\n\n /** Numeric value (`null` when empty). Bound by `[formField]`, or two-way via `[(value)]`. */\n readonly value = model<number | null>(null);\n\n /** Emitted on blur so a bound field can mark itself touched. */\n readonly touch = output<void>();\n\n private readonly locale = inject(LOCALE_ID);\n private readonly separators = resolveSeparators(this.locale);\n\n /** Text currently in the input (may be partial / invalid mid-type). */\n protected readonly text = signal<string>('');\n\n /** Whether the input is focused. While true, the input handlers own `text`. */\n protected readonly focused = signal(false);\n\n protected readonly interactive = computed(() => !this.disabled() && !this.readonly());\n\n protected readonly atMin = computed(() => {\n const v = this.value();\n return v !== null && v <= this.minValue();\n });\n\n protected readonly atMax = computed(() => {\n const v = this.value();\n return v !== null && v >= this.maxValue();\n });\n\n /**\n * The size and pill modifiers mirror what is bound down to the chrome, because\n * the stepper column belongs to neither half of it: the field carries\n * `wr-input--<size>`, the column is its SIBLING, and the group carries no size\n * at all. Without a modifier of its own the column drew one 10x6 chevron at\n * every size and ran its dividers into a pill's rounded end.\n */\n protected readonly classes = computed(() => {\n const parts = ['wr-input-number'];\n const size = this.resolvedSize();\n if (size !== 'md') parts.push(`wr-input-number--${size}`);\n if (this.resolvedRounded()) parts.push('wr-input-number--rounded');\n if (this.disabled()) parts.push('wr-input-number--disabled');\n return parts.join(' ');\n });\n\n /**\n * Fraction digits the stepper rounds its arithmetic to when `decimals` says\n * nothing. High enough to leave a real value alone, low enough to erase the\n * binary-float tail that repeated stepping accumulates.\n */\n private static readonly STEP_PRECISION = 10;\n\n /**\n * Above this, the anti-drift round is skipped — it would MANUFACTURE drift.\n *\n * `round(v, 10)` is `Math.round((v + EPSILON) * 1e10) / 1e10`, and the scale\n * factor is only exact while `v * 1e10` stays inside 2^53, i.e. |v| under\n * about 900,720. In practice the round-trip still recovers up to ~9.2e8 and\n * then breaks: `round(1000000001, 10)` is `1000000000.9999999`, and since\n * `format` prints up to 20 fraction digits that tail reaches the screen —\n * and compounds, because the next press starts from it. Integer stepping at\n * that magnitude is exact in IEEE754 and needed no help; the only thing this\n * rounding exists to defend is `0.1 + 0.1 + 0.1`.\n */\n private static readonly SAFE_ROUND_MAGNITUDE = 1e6;\n\n /** Steps finer than this would be rounded away by {@link STEP_PRECISION}. */\n private static readonly SAFE_ROUND_STEP = 1e-9;\n\n constructor() {\n // Keep the display `text` in sync with external writes to `value` (via\n // `[formField]` / `[(value)]`). While the user is editing, the input\n // handlers own `text`, so skip re-formatting to avoid clobbering partial\n // input (e.g. mid-typed grouping or a value that is still being clamped).\n effect(() => {\n const v = this.value();\n if (this.focused()) return;\n if (v === null || Number.isNaN(v)) {\n this.text.set('');\n return;\n }\n // SHOW WHAT THE MODEL HOLDS. It used to format `constrain(v)`, so a\n // `[max]=\"10\"` field handed 500 drew \"10\" over a model that still said\n // 500 — the display was the thing lying, not the model.\n //\n // The tempting repair is to write the clamp back so the two agree, and\n // that is worse: under `[formField]` the bounds arrive ONLY through the\n // schema's `min()` / `max()` rules (binding `[min]` next to `[formField]`\n // is an NG8022 compile error), so overwriting the value ERASES the very\n // error those rules exist to raise — and the write marks a pristine form\n // dirty, tripping unsaved-changes guards and opening every other\n // validator's message on first paint.\n //\n // So: `min` / `max` bound what this component's own edits may produce,\n // and a value written from outside is displayed as it is and left for\n // validation to judge.\n this.text.set(this.format(v));\n });\n }\n\n // Template handlers\n\n protected onInput(event: Event): void {\n const raw = (event.target as HTMLInputElement).value;\n this.text.set(raw);\n if (!raw.trim()) {\n this.value.set(null);\n return;\n }\n const parsed = this.parse(raw);\n if (parsed === null) return; // partial input — wait for more\n const next = this.constrain(parsed);\n this.value.set(next);\n }\n\n protected onFocus(): void {\n this.focused.set(true);\n }\n\n protected onBlur(): void {\n // Flipping `focused` false lets the sync effect re-format `text` from the\n // committed `value` (e.g. `\"1.\"` → `\"1\"`, or grouping the final number).\n this.focused.set(false);\n this.touch.emit();\n }\n\n protected onKeydown(event: KeyboardEvent): void {\n if (!this.interactive()) return;\n if (event.key !== 'ArrowUp' && event.key !== 'ArrowDown') return;\n event.preventDefault();\n const direction = event.key === 'ArrowUp' ? 1 : -1;\n const multiplier = event.shiftKey ? 10 : 1;\n this.bump(direction * multiplier);\n }\n\n protected stepBy(direction: 1 | -1): void {\n if (!this.interactive()) return;\n this.bump(direction);\n }\n\n // Internals\n\n private bump(units: number): void {\n const stepSize = this.step() || 1;\n const base = this.value() ?? this.fallbackBase();\n // `round` before `constrain`, and only on the stepped ARITHMETIC. Binary\n // floats do not add: three presses of a `step=\"0.1\"` stepper produced\n // 0.30000000000000004, `constrain` only rounds when `decimals` is set, and\n // `format` prints up to 20 fraction digits — so the drift went into the\n // model AND onto the screen. Ten digits erases IEEE noise without\n // quantising a value the user typed (0.15000000000000002 stays 0.15, it\n // does not snap to the step grid).\n //\n // Guarded on BOTH ends, because outside them the correction is the thing\n // that corrupts: see SAFE_ROUND_MAGNITUDE, and a step finer than 1e-9 would\n // simply be rounded away to nothing.\n const raw = base + units * stepSize;\n const correctable =\n Math.abs(raw) < WrInputNumber.SAFE_ROUND_MAGNITUDE && Math.abs(stepSize) >= WrInputNumber.SAFE_ROUND_STEP;\n const next = this.constrain(correctable ? round(raw, WrInputNumber.STEP_PRECISION) : raw);\n this.value.set(next);\n this.text.set(this.format(next));\n }\n\n /** Choose a sensible starting point when bumping from `null`. */\n private fallbackBase(): number {\n if (Number.isFinite(this.minValue()) && this.minValue() > 0) return this.minValue();\n if (Number.isFinite(this.maxValue()) && this.maxValue() < 0) return this.maxValue();\n return 0;\n }\n\n private constrain(v: number): number {\n let next = clamp(v, this.minValue(), this.maxValue());\n const d = this.decimals();\n if (d !== null) next = round(next, d);\n return next;\n }\n\n /** Parse a locale-formatted string. Returns `null` for partial / not-yet-numeric input. */\n private parse(raw: string): number | null {\n const trimmed = raw.trim();\n if (!trimmed) return null;\n // Strip group separators, normalise the decimal separator to `.`.\n let normalised = trimmed;\n if (this.separators.group) {\n normalised = normalised.split(this.separators.group).join('');\n }\n if (this.separators.decimal !== '.') {\n normalised = normalised.split(this.separators.decimal).join('.');\n }\n // Partial inputs we don't want to clobber while the user is still typing:\n // `-`, `-.`, `.`, `1.`, `-1.` etc.\n if (/^-?\\.?$/.test(normalised) || normalised.endsWith('.')) return null;\n const n = Number(normalised);\n return Number.isFinite(n) ? n : null;\n }\n\n /** Format a value using `Intl.NumberFormat` for the active locale. */\n private format(v: number): string {\n const d = this.decimals();\n const formatter = new Intl.NumberFormat(this.locale, {\n minimumFractionDigits: d ?? 0,\n maximumFractionDigits: d ?? 20,\n useGrouping: true,\n });\n return formatter.format(v);\n }\n}\n","<wr-input-group [rounded]=\"resolvedRounded()\">\n @if (prefix(); as p) {\n <span wrInputPrefix>{{ p }}</span>\n }\n <input\n #input\n wrInput\n type=\"text\"\n inputmode=\"decimal\"\n autocomplete=\"off\"\n [size]=\"resolvedSize()\"\n [rounded]=\"resolvedRounded()\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\n spellcheck=\"false\"\n [value]=\"text()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n (input)=\"onInput($event)\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n (keydown)=\"onKeydown($event)\"\n />\n @if (suffix(); as s) {\n <span wrInputSuffix>{{ s }}</span>\n }\n @if (showSteppers()) {\n <div class=\"wr-input-number__steppers\" wrInputSuffix>\n <button\n type=\"button\"\n class=\"wr-input-number__step\"\n tabindex=\"-1\"\n [attr.aria-label]=\"resolvedIncrement()\"\n [disabled]=\"!interactive() || atMax()\"\n (click)=\"stepBy(1)\"\n >\n <svg width=\"10\" height=\"6\" viewBox=\"0 0 8 5\" aria-hidden=\"true\">\n <path d=\"M0 5 L4 0 L8 5 Z\" fill=\"currentColor\" />\n </svg>\n </button>\n <button\n type=\"button\"\n class=\"wr-input-number__step\"\n tabindex=\"-1\"\n [attr.aria-label]=\"resolvedDecrement()\"\n [disabled]=\"!interactive() || atMin()\"\n (click)=\"stepBy(-1)\"\n >\n <svg width=\"10\" height=\"6\" viewBox=\"0 0 8 5\" aria-hidden=\"true\">\n <path d=\"M0 0 L4 5 L8 0 Z\" fill=\"currentColor\" />\n </svg>\n </button>\n </div>\n }\n</wr-input-group>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -57,6 +57,12 @@ class WrLineChart {
|
|
|
57
57
|
showLegend = input(true, { ...(ngDevMode ? { debugName: "showLegend" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
|
|
58
58
|
/** Show dots at each data point. @default true */
|
|
59
59
|
showDots = input(true, { ...(ngDevMode ? { debugName: "showDots" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
|
|
60
|
+
/**
|
|
61
|
+
* Show the hover readout: the crosshair, the point markers and the tooltip. Off
|
|
62
|
+
* drops all three, since a crosshair with no values beside it points at nothing.
|
|
63
|
+
* @default true
|
|
64
|
+
*/
|
|
65
|
+
tooltip = input(true, { ...(ngDevMode ? { debugName: "tooltip" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
|
|
60
66
|
// Drawn in a 600×300 viewBox with reserved space for axis labels.
|
|
61
67
|
vbW = 600;
|
|
62
68
|
vbH = 300;
|
|
@@ -65,6 +71,9 @@ class WrLineChart {
|
|
|
65
71
|
/** Hovered point index (across all series) — null when no hover. */
|
|
66
72
|
hoveredIndex = signal(null, /* @ts-ignore */
|
|
67
73
|
...(ngDevMode ? [{ debugName: "hoveredIndex" }] : /* istanbul ignore next */ []));
|
|
74
|
+
/** The hovered index while the readout is on, so turning `tooltip` off mid-hover clears it. */
|
|
75
|
+
activeIndex = computed(() => (this.tooltip() ? this.hoveredIndex() : null), /* @ts-ignore */
|
|
76
|
+
...(ngDevMode ? [{ debugName: "activeIndex" }] : /* istanbul ignore next */ []));
|
|
68
77
|
/**
|
|
69
78
|
* A dash pattern per series, so the lines are told apart by SHAPE and not
|
|
70
79
|
* only by hue.
|
|
@@ -197,7 +206,7 @@ class WrLineChart {
|
|
|
197
206
|
return Math.min(slot, x + slot / 2, 100 - x + slot / 2);
|
|
198
207
|
}
|
|
199
208
|
hoverPoints = computed(() => {
|
|
200
|
-
const i = this.
|
|
209
|
+
const i = this.activeIndex();
|
|
201
210
|
if (i === null)
|
|
202
211
|
return [];
|
|
203
212
|
return this.resolvedSeries().flatMap(s => {
|
|
@@ -211,13 +220,15 @@ class WrLineChart {
|
|
|
211
220
|
}, /* @ts-ignore */
|
|
212
221
|
...(ngDevMode ? [{ debugName: "hoverPoints" }] : /* istanbul ignore next */ []));
|
|
213
222
|
hoverLabel = computed(() => {
|
|
214
|
-
const i = this.
|
|
223
|
+
const i = this.activeIndex();
|
|
215
224
|
if (i === null)
|
|
216
225
|
return '';
|
|
217
226
|
return this.xLabels()[i] ?? String(i);
|
|
218
227
|
}, /* @ts-ignore */
|
|
219
228
|
...(ngDevMode ? [{ debugName: "hoverLabel" }] : /* istanbul ignore next */ []));
|
|
220
229
|
onPointerMove(event) {
|
|
230
|
+
if (!this.tooltip())
|
|
231
|
+
return;
|
|
221
232
|
const svg = event.currentTarget.getBoundingClientRect();
|
|
222
233
|
const ratio = (event.clientX - svg.left) / svg.width;
|
|
223
234
|
const vbX = ratio * this.vbW;
|
|
@@ -259,12 +270,12 @@ class WrLineChart {
|
|
|
259
270
|
// Convenience accessor so the host can be referenced from the template.
|
|
260
271
|
hostEl = this.host.nativeElement;
|
|
261
272
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrLineChart, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
262
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: WrLineChart, isStandalone: true, selector: "wr-line-chart", inputs: { series: { classPropertyName: "series", publicName: "series", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, xLabels: { classPropertyName: "xLabels", publicName: "xLabels", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, showGrid: { classPropertyName: "showGrid", publicName: "showGrid", isSignal: true, isRequired: false, transformFunction: null }, showLegend: { classPropertyName: "showLegend", publicName: "showLegend", isSignal: true, isRequired: false, transformFunction: null }, showDots: { classPropertyName: "showDots", publicName: "showDots", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "wr-line-chart" }, ngImport: i0, template: "@let hovered =
|
|
273
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: WrLineChart, isStandalone: true, selector: "wr-line-chart", inputs: { series: { classPropertyName: "series", publicName: "series", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, xLabels: { classPropertyName: "xLabels", publicName: "xLabels", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, showGrid: { classPropertyName: "showGrid", publicName: "showGrid", isSignal: true, isRequired: false, transformFunction: null }, showLegend: { classPropertyName: "showLegend", publicName: "showLegend", isSignal: true, isRequired: false, transformFunction: null }, showDots: { classPropertyName: "showDots", publicName: "showDots", isSignal: true, isRequired: false, transformFunction: null }, tooltip: { classPropertyName: "tooltip", publicName: "tooltip", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "wr-line-chart" }, ngImport: i0, template: "@let hovered = activeIndex();\n@if (showLegend() && resolvedSeries().length > 0) {\n <ul class=\"wr-line-chart__legend\">\n @for (s of resolvedSeries(); track s.label) {\n <li class=\"wr-line-chart__legend-item\">\n <!-- The swatch draws the series' own dash, not a solid block. A legend\n that pairs a coloured square with a name leaves the reader to match\n the square to the LINE, and matching by colour is the step the\n patterns exist to remove. -->\n <svg class=\"wr-line-chart__swatch\" viewBox=\"0 0 16 2\" aria-hidden=\"true\">\n <line\n x1=\"0\"\n y1=\"1\"\n x2=\"16\"\n y2=\"1\"\n [attr.stroke]=\"s.color\"\n [attr.stroke-dasharray]=\"s.dash || null\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n />\n </svg>\n <span>{{ s.label }}</span>\n </li>\n }\n </ul>\n}\n\n<div class=\"wr-line-chart__plot\" role=\"img\" [attr.aria-label]=\"resolvedAriaLabel()\" [style.height.px]=\"height()\">\n <!-- Named, where it was the only unnamed element in the component. The legend\n swatch is an `<svg>` too now, so `querySelector('svg')` no longer means\n \"the chart\" \u2014 and a plot that nothing can address by name is one a\n consumer's stylesheet and a spec both have to reach by position. -->\n <svg\n class=\"wr-line-chart__svg\"\n [attr.viewBox]=\"viewBox()\"\n preserveAspectRatio=\"none\"\n (pointermove)=\"onPointerMove($event)\"\n (pointerleave)=\"onPointerLeave()\"\n >\n @if (showGrid()) {\n @for (tick of yTicks(); track tick.value) {\n <line\n class=\"wr-line-chart__grid-line\"\n [attr.x1]=\"padding.left\"\n [attr.x2]=\"vbW - padding.right\"\n [attr.y1]=\"tick.y\"\n [attr.y2]=\"tick.y\"\n stroke=\"rgba(var(--wr-color-light-rgb), 0.7)\"\n stroke-width=\"1\"\n vector-effect=\"non-scaling-stroke\"\n />\n <text\n class=\"wr-line-chart__tick\"\n [attr.x]=\"padding.left - 6\"\n [attr.y]=\"tick.y + 4\"\n text-anchor=\"end\"\n fill=\"var(--wr-color-on-surface-muted)\"\n font-size=\"10\"\n font-family=\"var(--wr-font-family-base)\"\n >\n {{ formatTick(tick.value) }}\n </text>\n }\n }\n\n @for (s of resolvedSeries(); track s.label) {\n <path\n class=\"wr-line-chart__line\"\n [attr.d]=\"pathFor(s)\"\n fill=\"none\"\n [attr.stroke]=\"s.color\"\n [attr.stroke-dasharray]=\"s.dash || null\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n vector-effect=\"non-scaling-stroke\"\n />\n @if (showDots()) {\n @for (v of s.data; track $index; let i = $index) {\n <!-- A hole in the data gets no dot: the index still belongs to it, so the\n points after it stay on their own x. -->\n @if (v !== null) {\n <circle\n class=\"wr-line-chart__dot\"\n [attr.cx]=\"pointX(i)\"\n [attr.cy]=\"pointY(v)\"\n r=\"3\"\n [attr.fill]=\"s.color\"\n />\n }\n }\n }\n }\n\n @if (hovered !== null && hoverPoints().length > 0) {\n <line\n class=\"wr-line-chart__crosshair\"\n [attr.x1]=\"pointX(hovered)\"\n [attr.x2]=\"pointX(hovered)\"\n [attr.y1]=\"padding.top\"\n [attr.y2]=\"vbH - padding.bottom\"\n stroke=\"var(--wr-color-medium)\"\n stroke-width=\"1\"\n stroke-dasharray=\"3 3\"\n vector-effect=\"non-scaling-stroke\"\n />\n @for (p of hoverPoints(); track p.label) {\n <circle\n [attr.cx]=\"p.x\"\n [attr.cy]=\"p.y\"\n r=\"5\"\n fill=\"var(--wr-color-white)\"\n [attr.stroke]=\"p.color\"\n stroke-width=\"2\"\n />\n }\n }\n </svg>\n\n @if (hovered !== null && hoverPoints().length > 0) {\n <!-- The layer spans the plot and is what the tooltip's `cqw` measures. It is out of\n flow, so the containment it turns on costs the plot's own sizing nothing. The\n tooltip takes the same `--wr-line-chart-x` the x labels take, and the same clamp:\n centred on its point, never past either end. -->\n <div class=\"wr-line-chart__tooltip-layer\">\n <div\n class=\"wr-line-chart__tooltip\"\n [style.left.%]=\"xPercent(hovered)\"\n [style.--wr-line-chart-x]=\"xPercent(hovered)\"\n [style.top.px]=\"padding.top\"\n >\n <div class=\"wr-line-chart__tooltip-label\">{{ hoverLabel() }}</div>\n @for (p of hoverPoints(); track p.label) {\n <div class=\"wr-line-chart__tooltip-row\">\n <span class=\"wr-line-chart__swatch\" [style.background]=\"p.color\"></span>\n <span class=\"wr-line-chart__tooltip-name\">{{ p.label }}</span>\n <span class=\"wr-line-chart__tooltip-value\">{{ p.value }}</span>\n </div>\n }\n </div>\n </div>\n }\n</div>\n\n@if (xLabels().length > 0) {\n <div class=\"wr-line-chart__x-labels\">\n @for (label of xLabels(); track $index) {\n <!-- Each label hands the stylesheet two numbers, both percentages of the host's\n width \u2014 the space the stretching SVG is in, so they track the drawing at any\n size. The x of the point it names, which the stylesheet centres it on; and the\n widest it may be before it reaches a neighbour or the end of the strip, past\n which the stylesheet ellipsises it. Laying the labels out as equal centred flex\n slots instead is bar-chart geometry: only the middle label landed on its dot,\n and the outer ones sat up to half a column away. -->\n <span\n class=\"wr-line-chart__x-label\"\n [style.--wr-line-chart-x]=\"xPercent($index)\"\n [style.--wr-line-chart-x-max]=\"xMaxPercent($index)\"\n >{{ label }}</span\n >\n }\n </div>\n}\n", encapsulation: i0.ViewEncapsulation.None });
|
|
263
274
|
}
|
|
264
275
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrLineChart, decorators: [{
|
|
265
276
|
type: Component,
|
|
266
|
-
args: [{ selector: 'wr-line-chart', encapsulation: ViewEncapsulation.None, host: { class: 'wr-line-chart' }, template: "@let hovered =
|
|
267
|
-
}], propDecorators: { series: [{ type: i0.Input, args: [{ isSignal: true, alias: "series", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], xLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "xLabels", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], showGrid: [{ type: i0.Input, args: [{ isSignal: true, alias: "showGrid", required: false }] }], showLegend: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLegend", required: false }] }], showDots: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDots", required: false }] }] } });
|
|
277
|
+
args: [{ selector: 'wr-line-chart', encapsulation: ViewEncapsulation.None, host: { class: 'wr-line-chart' }, template: "@let hovered = activeIndex();\n@if (showLegend() && resolvedSeries().length > 0) {\n <ul class=\"wr-line-chart__legend\">\n @for (s of resolvedSeries(); track s.label) {\n <li class=\"wr-line-chart__legend-item\">\n <!-- The swatch draws the series' own dash, not a solid block. A legend\n that pairs a coloured square with a name leaves the reader to match\n the square to the LINE, and matching by colour is the step the\n patterns exist to remove. -->\n <svg class=\"wr-line-chart__swatch\" viewBox=\"0 0 16 2\" aria-hidden=\"true\">\n <line\n x1=\"0\"\n y1=\"1\"\n x2=\"16\"\n y2=\"1\"\n [attr.stroke]=\"s.color\"\n [attr.stroke-dasharray]=\"s.dash || null\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n />\n </svg>\n <span>{{ s.label }}</span>\n </li>\n }\n </ul>\n}\n\n<div class=\"wr-line-chart__plot\" role=\"img\" [attr.aria-label]=\"resolvedAriaLabel()\" [style.height.px]=\"height()\">\n <!-- Named, where it was the only unnamed element in the component. The legend\n swatch is an `<svg>` too now, so `querySelector('svg')` no longer means\n \"the chart\" \u2014 and a plot that nothing can address by name is one a\n consumer's stylesheet and a spec both have to reach by position. -->\n <svg\n class=\"wr-line-chart__svg\"\n [attr.viewBox]=\"viewBox()\"\n preserveAspectRatio=\"none\"\n (pointermove)=\"onPointerMove($event)\"\n (pointerleave)=\"onPointerLeave()\"\n >\n @if (showGrid()) {\n @for (tick of yTicks(); track tick.value) {\n <line\n class=\"wr-line-chart__grid-line\"\n [attr.x1]=\"padding.left\"\n [attr.x2]=\"vbW - padding.right\"\n [attr.y1]=\"tick.y\"\n [attr.y2]=\"tick.y\"\n stroke=\"rgba(var(--wr-color-light-rgb), 0.7)\"\n stroke-width=\"1\"\n vector-effect=\"non-scaling-stroke\"\n />\n <text\n class=\"wr-line-chart__tick\"\n [attr.x]=\"padding.left - 6\"\n [attr.y]=\"tick.y + 4\"\n text-anchor=\"end\"\n fill=\"var(--wr-color-on-surface-muted)\"\n font-size=\"10\"\n font-family=\"var(--wr-font-family-base)\"\n >\n {{ formatTick(tick.value) }}\n </text>\n }\n }\n\n @for (s of resolvedSeries(); track s.label) {\n <path\n class=\"wr-line-chart__line\"\n [attr.d]=\"pathFor(s)\"\n fill=\"none\"\n [attr.stroke]=\"s.color\"\n [attr.stroke-dasharray]=\"s.dash || null\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n vector-effect=\"non-scaling-stroke\"\n />\n @if (showDots()) {\n @for (v of s.data; track $index; let i = $index) {\n <!-- A hole in the data gets no dot: the index still belongs to it, so the\n points after it stay on their own x. -->\n @if (v !== null) {\n <circle\n class=\"wr-line-chart__dot\"\n [attr.cx]=\"pointX(i)\"\n [attr.cy]=\"pointY(v)\"\n r=\"3\"\n [attr.fill]=\"s.color\"\n />\n }\n }\n }\n }\n\n @if (hovered !== null && hoverPoints().length > 0) {\n <line\n class=\"wr-line-chart__crosshair\"\n [attr.x1]=\"pointX(hovered)\"\n [attr.x2]=\"pointX(hovered)\"\n [attr.y1]=\"padding.top\"\n [attr.y2]=\"vbH - padding.bottom\"\n stroke=\"var(--wr-color-medium)\"\n stroke-width=\"1\"\n stroke-dasharray=\"3 3\"\n vector-effect=\"non-scaling-stroke\"\n />\n @for (p of hoverPoints(); track p.label) {\n <circle\n [attr.cx]=\"p.x\"\n [attr.cy]=\"p.y\"\n r=\"5\"\n fill=\"var(--wr-color-white)\"\n [attr.stroke]=\"p.color\"\n stroke-width=\"2\"\n />\n }\n }\n </svg>\n\n @if (hovered !== null && hoverPoints().length > 0) {\n <!-- The layer spans the plot and is what the tooltip's `cqw` measures. It is out of\n flow, so the containment it turns on costs the plot's own sizing nothing. The\n tooltip takes the same `--wr-line-chart-x` the x labels take, and the same clamp:\n centred on its point, never past either end. -->\n <div class=\"wr-line-chart__tooltip-layer\">\n <div\n class=\"wr-line-chart__tooltip\"\n [style.left.%]=\"xPercent(hovered)\"\n [style.--wr-line-chart-x]=\"xPercent(hovered)\"\n [style.top.px]=\"padding.top\"\n >\n <div class=\"wr-line-chart__tooltip-label\">{{ hoverLabel() }}</div>\n @for (p of hoverPoints(); track p.label) {\n <div class=\"wr-line-chart__tooltip-row\">\n <span class=\"wr-line-chart__swatch\" [style.background]=\"p.color\"></span>\n <span class=\"wr-line-chart__tooltip-name\">{{ p.label }}</span>\n <span class=\"wr-line-chart__tooltip-value\">{{ p.value }}</span>\n </div>\n }\n </div>\n </div>\n }\n</div>\n\n@if (xLabels().length > 0) {\n <div class=\"wr-line-chart__x-labels\">\n @for (label of xLabels(); track $index) {\n <!-- Each label hands the stylesheet two numbers, both percentages of the host's\n width \u2014 the space the stretching SVG is in, so they track the drawing at any\n size. The x of the point it names, which the stylesheet centres it on; and the\n widest it may be before it reaches a neighbour or the end of the strip, past\n which the stylesheet ellipsises it. Laying the labels out as equal centred flex\n slots instead is bar-chart geometry: only the middle label landed on its dot,\n and the outer ones sat up to half a column away. -->\n <span\n class=\"wr-line-chart__x-label\"\n [style.--wr-line-chart-x]=\"xPercent($index)\"\n [style.--wr-line-chart-x-max]=\"xMaxPercent($index)\"\n >{{ label }}</span\n >\n }\n </div>\n}\n" }]
|
|
278
|
+
}], propDecorators: { series: [{ type: i0.Input, args: [{ isSignal: true, alias: "series", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], xLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "xLabels", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], showGrid: [{ type: i0.Input, args: [{ isSignal: true, alias: "showGrid", required: false }] }], showLegend: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLegend", required: false }] }], showDots: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDots", required: false }] }], tooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "tooltip", required: false }] }] } });
|
|
268
279
|
|
|
269
280
|
/**
|
|
270
281
|
* Generated bundle index. Do not edit.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngwr-line-chart.mjs","sources":["../../../projects/lib/line-chart/line-chart.ts","../../../projects/lib/line-chart/line-chart.html","../../../projects/lib/line-chart/ngwr-line-chart.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';\nimport { Component, ElementRef, LOCALE_ID, ViewEncapsulation, computed, inject, input, signal } from '@angular/core';\n\nimport { useI18nFormatter, useI18nText } from 'ngwr/i18n';\n\nimport type { WrLineSeries } from './interfaces';\n\nconst FALLBACK_COLORS = [\n 'var(--wr-color-primary)',\n 'var(--wr-color-secondary)',\n 'var(--wr-color-success)',\n 'var(--wr-color-warning)',\n 'var(--wr-color-danger)',\n];\n\n/**\n * Multi-series line chart with axes, gridlines, and a hover tooltip.\n * SVG-only — no external dependency.\n *\n * @example\n * ```html\n * <wr-line-chart\n * [series]=\"[\n * { label: 'Visits', data: [12, 18, 9, 22, 30, 27, 35] },\n * { label: 'Signups', data: [3, 5, 4, 8, 11, 9, 14], color: 'var(--wr-color-success)' }\n * ]\"\n * [xLabels]=\"['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']\"\n * />\n * ```\n *\n * @see https://ngwr.dev/reference/components/line-chart\n */\n@Component({\n selector: 'wr-line-chart',\n templateUrl: './line-chart.html',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-line-chart' },\n})\nexport class WrLineChart {\n readonly series = input<readonly WrLineSeries[]>([]);\n\n /**\n * Accessible name of the chart. The legend carries the series NAMES only — the numbers\n * are nowhere in text — so without this the plot is nothing at all to a screen reader.\n * Falls back to `lineChart.label`.\n */\n readonly ariaLabel = input<string | null>(null);\n\n protected readonly resolvedAriaLabel = useI18nText(this.ariaLabel, 'lineChart.label', 'Line chart');\n\n private readonly locale = inject(LOCALE_ID);\n private readonly thousandsText = useI18nFormatter('lineChart.thousands', '{{value}}k');\n\n /** Labels for the X axis (one per data point). */\n readonly xLabels = input<readonly string[]>([]);\n\n /** Chart pixel height. @default 240 */\n readonly height = input(240, { transform: (v: unknown): number => Math.max(80, coerceNumberProperty(v, 240)) });\n\n /** Show gridlines + axis ticks. @default true */\n readonly showGrid = input(true, { transform: coerceBooleanProperty });\n\n /** Show the legend above the chart. @default true */\n readonly showLegend = input(true, { transform: coerceBooleanProperty });\n\n /** Show dots at each data point. @default true */\n readonly showDots = input(true, { transform: coerceBooleanProperty });\n\n // Drawn in a 600×300 viewBox with reserved space for axis labels.\n protected readonly vbW = 600;\n protected readonly vbH = 300;\n protected readonly padding = { top: 16, right: 16, bottom: 28, left: 36 } as const;\n\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n\n /** Hovered point index (across all series) — null when no hover. */\n protected readonly hoveredIndex = signal<number | null>(null);\n\n /**\n * A dash pattern per series, so the lines are told apart by SHAPE and not\n * only by hue.\n *\n * The default palette's colours sit within about 1.06:1 of each other in\n * relative luminance — that is the whole nine-intent scale's constraint, and\n * it means a reader with red-green colour blindness sees several of these\n * strokes as one grey. A legend that pairs a coloured square with a name does\n * not rescue it: matching the square to the line is exactly the step that\n * needs hue. Distinguishing series by dash is the standard remedy and the\n * only one that survives greyscale, printing and a monochrome display.\n *\n * The FIRST entry is solid on purpose. A single-series chart is the common\n * case and there is nothing to tell apart in it, so it is left exactly as it\n * was; the patterns only appear once a second series does.\n */\n private static readonly DASHES = ['', '7 4', '2 3', '10 4 2 4', '1 4', '6 3 2 3'] as const;\n\n protected readonly resolvedSeries = computed(() =>\n this.series().map((s, i) => ({\n label: s.label,\n dash: WrLineChart.DASHES[i % WrLineChart.DASHES.length],\n // A non-finite point becomes a HOLE at its own index, not a missing element.\n // It cannot stay a number: `Math.min`/`Math.max` over the pooled data are both\n // NaN as soon as one datum is, so every coordinate in EVERY series came out\n // `NaN` — invalid path geometry, and the whole chart vanished rather than the\n // one bad point. But filtering it out closed the gap and slid every LATER point\n // one x-slot to the left, so each of them was drawn under, and reported in the\n // tooltip as, the wrong x label. A gap is kept as a gap and the line is broken\n // across it: interpolating would invent a reading the data never took.\n data: s.data.map(v => (Number.isFinite(v) ? v : null)),\n color: s.color ?? FALLBACK_COLORS[i % FALLBACK_COLORS.length],\n }))\n );\n\n protected readonly bounds = computed(() => {\n const all = this.resolvedSeries().flatMap(s => s.data.filter(v => v !== null));\n if (all.length === 0) return { min: 0, max: 1 };\n const min = Math.min(...all);\n const max = Math.max(...all);\n if (min === max) return { min: min - 1, max: max + 1 };\n // Pad upper bound by ~10% for breathing room.\n return { min: Math.min(0, min), max: max + (max - min) * 0.1 };\n });\n\n protected readonly pointCount = computed(() => {\n const maxLen = this.resolvedSeries().reduce((acc, s) => Math.max(acc, s.data.length), 0);\n return Math.max(maxLen, this.xLabels().length);\n });\n\n /** Y-axis tick marks (5 of them). */\n protected readonly yTicks = computed(() => {\n const { min, max } = this.bounds();\n const step = (max - min) / 4;\n return [0, 1, 2, 3, 4].map(i => {\n const value = max - i * step;\n return { value, y: this.padding.top + ((max - value) / (max - min)) * this.plotHeight() };\n });\n });\n\n protected readonly plotWidth = (): number => this.vbW - this.padding.left - this.padding.right;\n protected readonly plotHeight = (): number => this.vbH - this.padding.top - this.padding.bottom;\n\n /**\n * The SVG path for a series — one subpath per unbroken run, so a hole in the data\n * leaves a hole in the line rather than a straight segment across it.\n */\n protected pathFor(series: { data: readonly (number | null)[] }): string {\n const { min, max } = this.bounds();\n const count = this.pointCount();\n if (count <= 1) return '';\n const pw = this.plotWidth();\n const ph = this.plotHeight();\n\n const commands: string[] = [];\n let run = 0;\n let last = '';\n // A subpath of one `M` is not stroked at all, so a point with a gap on both sides\n // would simply vanish when `showDots` is off. Repeating it gives the round linecap\n // something to paint.\n const closeRun = (): void => {\n if (run === 1) commands.push(`L ${last}`);\n run = 0;\n };\n\n series.data.forEach((v, i) => {\n if (v === null) {\n closeRun();\n return;\n }\n const x = this.padding.left + (i / (count - 1)) * pw;\n const y = this.padding.top + ((max - v) / (max - min)) * ph;\n last = `${x.toFixed(2)} ${y.toFixed(2)}`;\n commands.push(`${run === 0 ? 'M' : 'L'} ${last}`);\n run++;\n });\n closeRun();\n\n return commands.join(' ');\n }\n\n protected pointX(index: number): number {\n const count = this.pointCount();\n if (count <= 1) return this.padding.left;\n return this.padding.left + (index / (count - 1)) * this.plotWidth();\n }\n\n protected pointY(value: number): number {\n const { min, max } = this.bounds();\n return this.padding.top + ((max - value) / (max - min)) * this.plotHeight();\n }\n\n /**\n * A point's x as a percentage of the host's width. The x-label strip and the SVG share\n * that width — the drawing stretches to it — so this is the same space the tooltip and\n * the labels are placed in, at any size.\n */\n protected xPercent(index: number): number {\n return (this.pointX(index) / this.vbW) * 100;\n }\n\n /**\n * How wide an x label may be, as a percentage of the host's width: its own slot — half\n * the distance to a neighbour on each side — cut back to what is left between its point\n * and the end of the strip. Centring a label on its point says nothing about its WIDTH,\n * and with no bound at all twelve month names printed over each other and the last one\n * hung outside the chart. Past this the stylesheet ellipsises.\n */\n protected xMaxPercent(index: number): number {\n const count = this.pointCount();\n // A single label has no neighbour to collide with and the whole strip to sit in.\n if (count <= 1) return 100;\n const slot = (this.plotWidth() / (count - 1) / this.vbW) * 100;\n const x = this.xPercent(index);\n return Math.min(slot, x + slot / 2, 100 - x + slot / 2);\n }\n\n protected readonly hoverPoints = computed(() => {\n const i = this.hoveredIndex();\n if (i === null) return [];\n return this.resolvedSeries().flatMap(s => {\n // Past the end of a short series, or on a hole in a longer one — either way there\n // is no reading at this x, so the series contributes neither a marker nor a row.\n const value = s.data[i];\n if (value === undefined || value === null) return [];\n return [{ label: s.label, value, color: s.color, x: this.pointX(i), y: this.pointY(value) }];\n });\n });\n\n protected readonly hoverLabel = computed(() => {\n const i = this.hoveredIndex();\n if (i === null) return '';\n return this.xLabels()[i] ?? String(i);\n });\n\n protected onPointerMove(event: PointerEvent): void {\n const svg = (event.currentTarget as SVGElement).getBoundingClientRect();\n const ratio = (event.clientX - svg.left) / svg.width;\n const vbX = ratio * this.vbW;\n const count = this.pointCount();\n if (count === 0) return;\n const i = Math.round(((vbX - this.padding.left) / this.plotWidth()) * (count - 1));\n if (i >= 0 && i < count) this.hoveredIndex.set(i);\n }\n\n protected onPointerLeave(): void {\n this.hoveredIndex.set(null);\n }\n\n /**\n * A Y-axis tick, in the reader's own language.\n *\n * Two halves and both were English. The `k` was a hardcoded Latin\n * abbreviation — `тыс.` in Russian — so it goes through the catalog like every\n * other word the library paints. The digits went through `toFixed`, which\n * always writes a full stop, so a German axis read `1.5` where the rest of the\n * page read `1,5`; they go through `Intl` now, the way `wrNumber`, `wrDate`\n * and `wrPlural` already did.\n *\n * Grouping is OFF deliberately: a tick is a short axis label, and `5,000k`\n * would be both wider and a change to what every existing chart draws.\n */\n protected formatTick(v: number): string {\n const digits = (n: number, fraction: number): string =>\n new Intl.NumberFormat(this.locale, {\n useGrouping: false,\n minimumFractionDigits: fraction,\n maximumFractionDigits: fraction,\n }).format(n);\n\n if (Math.abs(v) >= 1000) return this.thousandsText({ value: digits(v / 1000, v % 1000 === 0 ? 0 : 1) });\n return digits(v, v % 1 === 0 ? 0 : 1);\n }\n\n protected readonly viewBox = computed(() => `0 0 ${this.vbW} ${this.vbH}`);\n\n // Convenience accessor so the host can be referenced from the template.\n protected readonly hostEl = this.host.nativeElement;\n}\n\nexport type { WrLineSeries } from './interfaces';\n","@let hovered = hoveredIndex();\n@if (showLegend() && resolvedSeries().length > 0) {\n <ul class=\"wr-line-chart__legend\">\n @for (s of resolvedSeries(); track s.label) {\n <li class=\"wr-line-chart__legend-item\">\n <!-- The swatch draws the series' own dash, not a solid block. A legend\n that pairs a coloured square with a name leaves the reader to match\n the square to the LINE, and matching by colour is the step the\n patterns exist to remove. -->\n <svg class=\"wr-line-chart__swatch\" viewBox=\"0 0 16 2\" aria-hidden=\"true\">\n <line\n x1=\"0\"\n y1=\"1\"\n x2=\"16\"\n y2=\"1\"\n [attr.stroke]=\"s.color\"\n [attr.stroke-dasharray]=\"s.dash || null\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n />\n </svg>\n <span>{{ s.label }}</span>\n </li>\n }\n </ul>\n}\n\n<div class=\"wr-line-chart__plot\" role=\"img\" [attr.aria-label]=\"resolvedAriaLabel()\" [style.height.px]=\"height()\">\n <!-- Named, where it was the only unnamed element in the component. The legend\n swatch is an `<svg>` too now, so `querySelector('svg')` no longer means\n \"the chart\" — and a plot that nothing can address by name is one a\n consumer's stylesheet and a spec both have to reach by position. -->\n <svg\n class=\"wr-line-chart__svg\"\n [attr.viewBox]=\"viewBox()\"\n preserveAspectRatio=\"none\"\n (pointermove)=\"onPointerMove($event)\"\n (pointerleave)=\"onPointerLeave()\"\n >\n @if (showGrid()) {\n @for (tick of yTicks(); track tick.value) {\n <line\n class=\"wr-line-chart__grid-line\"\n [attr.x1]=\"padding.left\"\n [attr.x2]=\"vbW - padding.right\"\n [attr.y1]=\"tick.y\"\n [attr.y2]=\"tick.y\"\n stroke=\"rgba(var(--wr-color-light-rgb), 0.7)\"\n stroke-width=\"1\"\n vector-effect=\"non-scaling-stroke\"\n />\n <text\n class=\"wr-line-chart__tick\"\n [attr.x]=\"padding.left - 6\"\n [attr.y]=\"tick.y + 4\"\n text-anchor=\"end\"\n fill=\"var(--wr-color-on-surface-muted)\"\n font-size=\"10\"\n font-family=\"var(--wr-font-family-base)\"\n >\n {{ formatTick(tick.value) }}\n </text>\n }\n }\n\n @for (s of resolvedSeries(); track s.label) {\n <path\n class=\"wr-line-chart__line\"\n [attr.d]=\"pathFor(s)\"\n fill=\"none\"\n [attr.stroke]=\"s.color\"\n [attr.stroke-dasharray]=\"s.dash || null\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n vector-effect=\"non-scaling-stroke\"\n />\n @if (showDots()) {\n @for (v of s.data; track $index; let i = $index) {\n <!-- A hole in the data gets no dot: the index still belongs to it, so the\n points after it stay on their own x. -->\n @if (v !== null) {\n <circle\n class=\"wr-line-chart__dot\"\n [attr.cx]=\"pointX(i)\"\n [attr.cy]=\"pointY(v)\"\n r=\"3\"\n [attr.fill]=\"s.color\"\n />\n }\n }\n }\n }\n\n @if (hovered !== null && hoverPoints().length > 0) {\n <line\n class=\"wr-line-chart__crosshair\"\n [attr.x1]=\"pointX(hovered)\"\n [attr.x2]=\"pointX(hovered)\"\n [attr.y1]=\"padding.top\"\n [attr.y2]=\"vbH - padding.bottom\"\n stroke=\"var(--wr-color-medium)\"\n stroke-width=\"1\"\n stroke-dasharray=\"3 3\"\n vector-effect=\"non-scaling-stroke\"\n />\n @for (p of hoverPoints(); track p.label) {\n <circle\n [attr.cx]=\"p.x\"\n [attr.cy]=\"p.y\"\n r=\"5\"\n fill=\"var(--wr-color-white)\"\n [attr.stroke]=\"p.color\"\n stroke-width=\"2\"\n />\n }\n }\n </svg>\n\n @if (hovered !== null && hoverPoints().length > 0) {\n <div class=\"wr-line-chart__tooltip\" [style.left.%]=\"(pointX(hovered) / vbW) * 100\" [style.top.px]=\"padding.top\">\n <div class=\"wr-line-chart__tooltip-label\">{{ hoverLabel() }}</div>\n @for (p of hoverPoints(); track p.label) {\n <div class=\"wr-line-chart__tooltip-row\">\n <span class=\"wr-line-chart__swatch\" [style.background]=\"p.color\"></span>\n <span class=\"wr-line-chart__tooltip-name\">{{ p.label }}</span>\n <span class=\"wr-line-chart__tooltip-value\">{{ p.value }}</span>\n </div>\n }\n </div>\n }\n</div>\n\n@if (xLabels().length > 0) {\n <div class=\"wr-line-chart__x-labels\">\n @for (label of xLabels(); track $index) {\n <!-- Each label hands the stylesheet two numbers, both percentages of the host's\n width — the space the stretching SVG is in, so they track the drawing at any\n size. The x of the point it names, which the stylesheet centres it on; and the\n widest it may be before it reaches a neighbour or the end of the strip, past\n which the stylesheet ellipsises it. Laying the labels out as equal centred flex\n slots instead is bar-chart geometry: only the middle label landed on its dot,\n and the outer ones sat up to half a column away. -->\n <span\n class=\"wr-line-chart__x-label\"\n [style.--wr-line-chart-x]=\"xPercent($index)\"\n [style.--wr-line-chart-x-max]=\"xMaxPercent($index)\"\n >{{ label }}</span\n >\n }\n </div>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;;AAAA;;;;;AAKG;AASH,MAAM,eAAe,GAAG;IACtB,yBAAyB;IACzB,2BAA2B;IAC3B,yBAAyB;IACzB,yBAAyB;IACzB,wBAAwB;CACzB;AAED;;;;;;;;;;;;;;;;AAgBG;MAOU,WAAW,CAAA;IACb,MAAM,GAAG,KAAK,CAA0B,EAAE;+EAAC;AAEpD;;;;AAIG;IACM,SAAS,GAAG,KAAK,CAAgB,IAAI;kFAAC;IAE5B,iBAAiB,GAAG,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,EAAE,YAAY,CAAC;AAElF,IAAA,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC;AAC1B,IAAA,aAAa,GAAG,gBAAgB,CAAC,qBAAqB,EAAE,YAAY,CAAC;;IAG7E,OAAO,GAAG,KAAK,CAAoB,EAAE;gFAAC;;IAGtC,MAAM,GAAG,KAAK,CAAC,GAAG,EAAA,EAAA,IAAA,SAAA,GAAA,EAAA,SAAA,EAAA,QAAA,EAAA,8BAAA,EAAA,CAAA,EAAI,SAAS,EAAE,CAAC,CAAU,KAAa,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,oBAAoB,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAA,CAAG;;IAGtG,QAAQ,GAAG,KAAK,CAAC,IAAI,gFAAI,SAAS,EAAE,qBAAqB,EAAA,CAAG;;IAG5D,UAAU,GAAG,KAAK,CAAC,IAAI,kFAAI,SAAS,EAAE,qBAAqB,EAAA,CAAG;;IAG9D,QAAQ,GAAG,KAAK,CAAC,IAAI,gFAAI,SAAS,EAAE,qBAAqB,EAAA,CAAG;;IAGlD,GAAG,GAAG,GAAG;IACT,GAAG,GAAG,GAAG;AACT,IAAA,OAAO,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAW;AAEjE,IAAA,IAAI,GAAG,MAAM,CAA0B,UAAU,CAAC;;IAGhD,YAAY,GAAG,MAAM,CAAgB,IAAI;qFAAC;AAE7D;;;;;;;;;;;;;;;AAeG;AACK,IAAA,OAAgB,MAAM,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,CAAU;IAEvE,cAAc,GAAG,QAAQ,CAAC,MAC3C,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM;QAC3B,KAAK,EAAE,CAAC,CAAC,KAAK;AACd,QAAA,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC;;;;;;;;;QASvD,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;AACtD,QAAA,KAAK,EAAE,CAAC,CAAC,KAAK,IAAI,eAAe,CAAC,CAAC,GAAG,eAAe,CAAC,MAAM,CAAC;AAC9D,KAAA,CAAC,CAAC;uFACJ;AAEkB,IAAA,MAAM,GAAG,QAAQ,CAAC,MAAK;AACxC,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC;AAC9E,QAAA,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE;QAC/C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;QAC5B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;QAC5B,IAAI,GAAG,KAAK,GAAG;AAAE,YAAA,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC,EAAE;;QAEtD,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC,GAAG,GAAG,GAAG,IAAI,GAAG,EAAE;IAChE,CAAC;+EAAC;AAEiB,IAAA,UAAU,GAAG,QAAQ,CAAC,MAAK;AAC5C,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AACxF,QAAA,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC;IAChD,CAAC;mFAAC;;AAGiB,IAAA,MAAM,GAAG,QAAQ,CAAC,MAAK;QACxC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE;QAClC,MAAM,IAAI,GAAG,CAAC,GAAG,GAAG,GAAG,IAAI,CAAC;AAC5B,QAAA,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAG;AAC7B,YAAA,MAAM,KAAK,GAAG,GAAG,GAAG,CAAC,GAAG,IAAI;AAC5B,YAAA,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,KAAK,KAAK,GAAG,GAAG,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,EAAE,EAAE;AAC3F,QAAA,CAAC,CAAC;IACJ,CAAC;+EAAC;AAEiB,IAAA,SAAS,GAAG,MAAc,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK;AAC3E,IAAA,UAAU,GAAG,MAAc,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM;AAE/F;;;AAGG;AACO,IAAA,OAAO,CAAC,MAA4C,EAAA;QAC5D,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE;AAClC,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,EAAE;QAC/B,IAAI,KAAK,IAAI,CAAC;AAAE,YAAA,OAAO,EAAE;AACzB,QAAA,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE;AAC3B,QAAA,MAAM,EAAE,GAAG,IAAI,CAAC,UAAU,EAAE;QAE5B,MAAM,QAAQ,GAAa,EAAE;QAC7B,IAAI,GAAG,GAAG,CAAC;QACX,IAAI,IAAI,GAAG,EAAE;;;;QAIb,MAAM,QAAQ,GAAG,MAAW;YAC1B,IAAI,GAAG,KAAK,CAAC;AAAE,gBAAA,QAAQ,CAAC,IAAI,CAAC,KAAK,IAAI,CAAA,CAAE,CAAC;YACzC,GAAG,GAAG,CAAC;AACT,QAAA,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,KAAI;AAC3B,YAAA,IAAI,CAAC,KAAK,IAAI,EAAE;AACd,gBAAA,QAAQ,EAAE;gBACV;YACF;AACA,YAAA,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,IAAI,EAAE;YACpD,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,KAAK,GAAG,GAAG,GAAG,CAAC,IAAI,EAAE;AAC3D,YAAA,IAAI,GAAG,CAAA,EAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA,CAAA,EAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;AACxC,YAAA,QAAQ,CAAC,IAAI,CAAC,GAAG,GAAG,KAAK,CAAC,GAAG,GAAG,GAAG,GAAG,IAAI,IAAI,CAAA,CAAE,CAAC;AACjD,YAAA,GAAG,EAAE;AACP,QAAA,CAAC,CAAC;AACF,QAAA,QAAQ,EAAE;AAEV,QAAA,OAAO,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC;IAC3B;AAEU,IAAA,MAAM,CAAC,KAAa,EAAA;AAC5B,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,EAAE;QAC/B,IAAI,KAAK,IAAI,CAAC;AAAE,YAAA,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI;QACxC,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,KAAK,IAAI,KAAK,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,EAAE;IACrE;AAEU,IAAA,MAAM,CAAC,KAAa,EAAA;QAC5B,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE;QAClC,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,KAAK,KAAK,GAAG,GAAG,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,EAAE;IAC7E;AAEA;;;;AAIG;AACO,IAAA,QAAQ,CAAC,KAAa,EAAA;AAC9B,QAAA,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,GAAG;IAC9C;AAEA;;;;;;AAMG;AACO,IAAA,WAAW,CAAC,KAAa,EAAA;AACjC,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,EAAE;;QAE/B,IAAI,KAAK,IAAI,CAAC;AAAE,YAAA,OAAO,GAAG;QAC1B,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,KAAK,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,GAAG;QAC9D,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAC9B,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC;IACzD;AAEmB,IAAA,WAAW,GAAG,QAAQ,CAAC,MAAK;AAC7C,QAAA,MAAM,CAAC,GAAG,IAAI,CAAC,YAAY,EAAE;QAC7B,IAAI,CAAC,KAAK,IAAI;AAAE,YAAA,OAAO,EAAE;QACzB,OAAO,IAAI,CAAC,cAAc,EAAE,CAAC,OAAO,CAAC,CAAC,IAAG;;;YAGvC,MAAM,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AACvB,YAAA,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;AAAE,gBAAA,OAAO,EAAE;AACpD,YAAA,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;AAC9F,QAAA,CAAC,CAAC;IACJ,CAAC;oFAAC;AAEiB,IAAA,UAAU,GAAG,QAAQ,CAAC,MAAK;AAC5C,QAAA,MAAM,CAAC,GAAG,IAAI,CAAC,YAAY,EAAE;QAC7B,IAAI,CAAC,KAAK,IAAI;AAAE,YAAA,OAAO,EAAE;AACzB,QAAA,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC;IACvC,CAAC;mFAAC;AAEQ,IAAA,aAAa,CAAC,KAAmB,EAAA;QACzC,MAAM,GAAG,GAAI,KAAK,CAAC,aAA4B,CAAC,qBAAqB,EAAE;AACvE,QAAA,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC,OAAO,GAAG,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,KAAK;AACpD,QAAA,MAAM,GAAG,GAAG,KAAK,GAAG,IAAI,CAAC,GAAG;AAC5B,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,EAAE;QAC/B,IAAI,KAAK,KAAK,CAAC;YAAE;AACjB,QAAA,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,SAAS,EAAE,KAAK,KAAK,GAAG,CAAC,CAAC,CAAC;AAClF,QAAA,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK;AAAE,YAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;IACnD;IAEU,cAAc,GAAA;AACtB,QAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC;IAC7B;AAEA;;;;;;;;;;;;AAYG;AACO,IAAA,UAAU,CAAC,CAAS,EAAA;AAC5B,QAAA,MAAM,MAAM,GAAG,CAAC,CAAS,EAAE,QAAgB,KACzC,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,EAAE;AACjC,YAAA,WAAW,EAAE,KAAK;AAClB,YAAA,qBAAqB,EAAE,QAAQ;AAC/B,YAAA,qBAAqB,EAAE,QAAQ;AAChC,SAAA,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;AAEd,QAAA,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI;AAAE,YAAA,OAAO,IAAI,CAAC,aAAa,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;AACvG,QAAA,OAAO,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACvC;AAEmB,IAAA,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAA,IAAA,EAAO,IAAI,CAAC,GAAG,CAAA,CAAA,EAAI,IAAI,CAAC,GAAG,CAAA,CAAE;gFAAC;;AAGvD,IAAA,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa;uGA7OxC,WAAW,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAX,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,WAAW,igCC7CxB,0jLAwJA,EAAA,aAAA,EAAA,EAAA,CAAA,iBAAA,CAAA,IAAA,EAAA,CAAA;;2FD3Ga,WAAW,EAAA,UAAA,EAAA,CAAA;kBANvB,SAAS;+BACE,eAAe,EAAA,aAAA,EAEV,iBAAiB,CAAC,IAAI,QAC/B,EAAE,KAAK,EAAE,eAAe,EAAE,EAAA,QAAA,EAAA,0jLAAA,EAAA;;;AE3ClC;;AAEG;;;;"}
|
|
1
|
+
{"version":3,"file":"ngwr-line-chart.mjs","sources":["../../../projects/lib/line-chart/line-chart.ts","../../../projects/lib/line-chart/line-chart.html","../../../projects/lib/line-chart/ngwr-line-chart.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';\nimport { Component, ElementRef, LOCALE_ID, ViewEncapsulation, computed, inject, input, signal } from '@angular/core';\n\nimport { useI18nFormatter, useI18nText } from 'ngwr/i18n';\n\nimport type { WrLineSeries } from './interfaces';\n\nconst FALLBACK_COLORS = [\n 'var(--wr-color-primary)',\n 'var(--wr-color-secondary)',\n 'var(--wr-color-success)',\n 'var(--wr-color-warning)',\n 'var(--wr-color-danger)',\n];\n\n/**\n * Multi-series line chart with axes, gridlines, and a hover tooltip.\n * SVG-only — no external dependency.\n *\n * @example\n * ```html\n * <wr-line-chart\n * [series]=\"[\n * { label: 'Visits', data: [12, 18, 9, 22, 30, 27, 35] },\n * { label: 'Signups', data: [3, 5, 4, 8, 11, 9, 14], color: 'var(--wr-color-success)' }\n * ]\"\n * [xLabels]=\"['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']\"\n * />\n * ```\n *\n * @see https://ngwr.dev/reference/components/line-chart\n */\n@Component({\n selector: 'wr-line-chart',\n templateUrl: './line-chart.html',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-line-chart' },\n})\nexport class WrLineChart {\n readonly series = input<readonly WrLineSeries[]>([]);\n\n /**\n * Accessible name of the chart. The legend carries the series NAMES only — the numbers\n * are nowhere in text — so without this the plot is nothing at all to a screen reader.\n * Falls back to `lineChart.label`.\n */\n readonly ariaLabel = input<string | null>(null);\n\n protected readonly resolvedAriaLabel = useI18nText(this.ariaLabel, 'lineChart.label', 'Line chart');\n\n private readonly locale = inject(LOCALE_ID);\n private readonly thousandsText = useI18nFormatter('lineChart.thousands', '{{value}}k');\n\n /** Labels for the X axis (one per data point). */\n readonly xLabels = input<readonly string[]>([]);\n\n /** Chart pixel height. @default 240 */\n readonly height = input(240, { transform: (v: unknown): number => Math.max(80, coerceNumberProperty(v, 240)) });\n\n /** Show gridlines + axis ticks. @default true */\n readonly showGrid = input(true, { transform: coerceBooleanProperty });\n\n /** Show the legend above the chart. @default true */\n readonly showLegend = input(true, { transform: coerceBooleanProperty });\n\n /** Show dots at each data point. @default true */\n readonly showDots = input(true, { transform: coerceBooleanProperty });\n\n /**\n * Show the hover readout: the crosshair, the point markers and the tooltip. Off\n * drops all three, since a crosshair with no values beside it points at nothing.\n * @default true\n */\n readonly tooltip = input(true, { transform: coerceBooleanProperty });\n\n // Drawn in a 600×300 viewBox with reserved space for axis labels.\n protected readonly vbW = 600;\n protected readonly vbH = 300;\n protected readonly padding = { top: 16, right: 16, bottom: 28, left: 36 } as const;\n\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n\n /** Hovered point index (across all series) — null when no hover. */\n protected readonly hoveredIndex = signal<number | null>(null);\n\n /** The hovered index while the readout is on, so turning `tooltip` off mid-hover clears it. */\n protected readonly activeIndex = computed(() => (this.tooltip() ? this.hoveredIndex() : null));\n\n /**\n * A dash pattern per series, so the lines are told apart by SHAPE and not\n * only by hue.\n *\n * The default palette's colours sit within about 1.06:1 of each other in\n * relative luminance — that is the whole nine-intent scale's constraint, and\n * it means a reader with red-green colour blindness sees several of these\n * strokes as one grey. A legend that pairs a coloured square with a name does\n * not rescue it: matching the square to the line is exactly the step that\n * needs hue. Distinguishing series by dash is the standard remedy and the\n * only one that survives greyscale, printing and a monochrome display.\n *\n * The FIRST entry is solid on purpose. A single-series chart is the common\n * case and there is nothing to tell apart in it, so it is left exactly as it\n * was; the patterns only appear once a second series does.\n */\n private static readonly DASHES = ['', '7 4', '2 3', '10 4 2 4', '1 4', '6 3 2 3'] as const;\n\n protected readonly resolvedSeries = computed(() =>\n this.series().map((s, i) => ({\n label: s.label,\n dash: WrLineChart.DASHES[i % WrLineChart.DASHES.length],\n // A non-finite point becomes a HOLE at its own index, not a missing element.\n // It cannot stay a number: `Math.min`/`Math.max` over the pooled data are both\n // NaN as soon as one datum is, so every coordinate in EVERY series came out\n // `NaN` — invalid path geometry, and the whole chart vanished rather than the\n // one bad point. But filtering it out closed the gap and slid every LATER point\n // one x-slot to the left, so each of them was drawn under, and reported in the\n // tooltip as, the wrong x label. A gap is kept as a gap and the line is broken\n // across it: interpolating would invent a reading the data never took.\n data: s.data.map(v => (Number.isFinite(v) ? v : null)),\n color: s.color ?? FALLBACK_COLORS[i % FALLBACK_COLORS.length],\n }))\n );\n\n protected readonly bounds = computed(() => {\n const all = this.resolvedSeries().flatMap(s => s.data.filter(v => v !== null));\n if (all.length === 0) return { min: 0, max: 1 };\n const min = Math.min(...all);\n const max = Math.max(...all);\n if (min === max) return { min: min - 1, max: max + 1 };\n // Pad upper bound by ~10% for breathing room.\n return { min: Math.min(0, min), max: max + (max - min) * 0.1 };\n });\n\n protected readonly pointCount = computed(() => {\n const maxLen = this.resolvedSeries().reduce((acc, s) => Math.max(acc, s.data.length), 0);\n return Math.max(maxLen, this.xLabels().length);\n });\n\n /** Y-axis tick marks (5 of them). */\n protected readonly yTicks = computed(() => {\n const { min, max } = this.bounds();\n const step = (max - min) / 4;\n return [0, 1, 2, 3, 4].map(i => {\n const value = max - i * step;\n return { value, y: this.padding.top + ((max - value) / (max - min)) * this.plotHeight() };\n });\n });\n\n protected readonly plotWidth = (): number => this.vbW - this.padding.left - this.padding.right;\n protected readonly plotHeight = (): number => this.vbH - this.padding.top - this.padding.bottom;\n\n /**\n * The SVG path for a series — one subpath per unbroken run, so a hole in the data\n * leaves a hole in the line rather than a straight segment across it.\n */\n protected pathFor(series: { data: readonly (number | null)[] }): string {\n const { min, max } = this.bounds();\n const count = this.pointCount();\n if (count <= 1) return '';\n const pw = this.plotWidth();\n const ph = this.plotHeight();\n\n const commands: string[] = [];\n let run = 0;\n let last = '';\n // A subpath of one `M` is not stroked at all, so a point with a gap on both sides\n // would simply vanish when `showDots` is off. Repeating it gives the round linecap\n // something to paint.\n const closeRun = (): void => {\n if (run === 1) commands.push(`L ${last}`);\n run = 0;\n };\n\n series.data.forEach((v, i) => {\n if (v === null) {\n closeRun();\n return;\n }\n const x = this.padding.left + (i / (count - 1)) * pw;\n const y = this.padding.top + ((max - v) / (max - min)) * ph;\n last = `${x.toFixed(2)} ${y.toFixed(2)}`;\n commands.push(`${run === 0 ? 'M' : 'L'} ${last}`);\n run++;\n });\n closeRun();\n\n return commands.join(' ');\n }\n\n protected pointX(index: number): number {\n const count = this.pointCount();\n if (count <= 1) return this.padding.left;\n return this.padding.left + (index / (count - 1)) * this.plotWidth();\n }\n\n protected pointY(value: number): number {\n const { min, max } = this.bounds();\n return this.padding.top + ((max - value) / (max - min)) * this.plotHeight();\n }\n\n /**\n * A point's x as a percentage of the host's width. The x-label strip and the SVG share\n * that width — the drawing stretches to it — so this is the same space the tooltip and\n * the labels are placed in, at any size.\n */\n protected xPercent(index: number): number {\n return (this.pointX(index) / this.vbW) * 100;\n }\n\n /**\n * How wide an x label may be, as a percentage of the host's width: its own slot — half\n * the distance to a neighbour on each side — cut back to what is left between its point\n * and the end of the strip. Centring a label on its point says nothing about its WIDTH,\n * and with no bound at all twelve month names printed over each other and the last one\n * hung outside the chart. Past this the stylesheet ellipsises.\n */\n protected xMaxPercent(index: number): number {\n const count = this.pointCount();\n // A single label has no neighbour to collide with and the whole strip to sit in.\n if (count <= 1) return 100;\n const slot = (this.plotWidth() / (count - 1) / this.vbW) * 100;\n const x = this.xPercent(index);\n return Math.min(slot, x + slot / 2, 100 - x + slot / 2);\n }\n\n protected readonly hoverPoints = computed(() => {\n const i = this.activeIndex();\n if (i === null) return [];\n return this.resolvedSeries().flatMap(s => {\n // Past the end of a short series, or on a hole in a longer one — either way there\n // is no reading at this x, so the series contributes neither a marker nor a row.\n const value = s.data[i];\n if (value === undefined || value === null) return [];\n return [{ label: s.label, value, color: s.color, x: this.pointX(i), y: this.pointY(value) }];\n });\n });\n\n protected readonly hoverLabel = computed(() => {\n const i = this.activeIndex();\n if (i === null) return '';\n return this.xLabels()[i] ?? String(i);\n });\n\n protected onPointerMove(event: PointerEvent): void {\n if (!this.tooltip()) return;\n const svg = (event.currentTarget as SVGElement).getBoundingClientRect();\n const ratio = (event.clientX - svg.left) / svg.width;\n const vbX = ratio * this.vbW;\n const count = this.pointCount();\n if (count === 0) return;\n const i = Math.round(((vbX - this.padding.left) / this.plotWidth()) * (count - 1));\n if (i >= 0 && i < count) this.hoveredIndex.set(i);\n }\n\n protected onPointerLeave(): void {\n this.hoveredIndex.set(null);\n }\n\n /**\n * A Y-axis tick, in the reader's own language.\n *\n * Two halves and both were English. The `k` was a hardcoded Latin\n * abbreviation — `тыс.` in Russian — so it goes through the catalog like every\n * other word the library paints. The digits went through `toFixed`, which\n * always writes a full stop, so a German axis read `1.5` where the rest of the\n * page read `1,5`; they go through `Intl` now, the way `wrNumber`, `wrDate`\n * and `wrPlural` already did.\n *\n * Grouping is OFF deliberately: a tick is a short axis label, and `5,000k`\n * would be both wider and a change to what every existing chart draws.\n */\n protected formatTick(v: number): string {\n const digits = (n: number, fraction: number): string =>\n new Intl.NumberFormat(this.locale, {\n useGrouping: false,\n minimumFractionDigits: fraction,\n maximumFractionDigits: fraction,\n }).format(n);\n\n if (Math.abs(v) >= 1000) return this.thousandsText({ value: digits(v / 1000, v % 1000 === 0 ? 0 : 1) });\n return digits(v, v % 1 === 0 ? 0 : 1);\n }\n\n protected readonly viewBox = computed(() => `0 0 ${this.vbW} ${this.vbH}`);\n\n // Convenience accessor so the host can be referenced from the template.\n protected readonly hostEl = this.host.nativeElement;\n}\n\nexport type { WrLineSeries } from './interfaces';\n","@let hovered = activeIndex();\n@if (showLegend() && resolvedSeries().length > 0) {\n <ul class=\"wr-line-chart__legend\">\n @for (s of resolvedSeries(); track s.label) {\n <li class=\"wr-line-chart__legend-item\">\n <!-- The swatch draws the series' own dash, not a solid block. A legend\n that pairs a coloured square with a name leaves the reader to match\n the square to the LINE, and matching by colour is the step the\n patterns exist to remove. -->\n <svg class=\"wr-line-chart__swatch\" viewBox=\"0 0 16 2\" aria-hidden=\"true\">\n <line\n x1=\"0\"\n y1=\"1\"\n x2=\"16\"\n y2=\"1\"\n [attr.stroke]=\"s.color\"\n [attr.stroke-dasharray]=\"s.dash || null\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n />\n </svg>\n <span>{{ s.label }}</span>\n </li>\n }\n </ul>\n}\n\n<div class=\"wr-line-chart__plot\" role=\"img\" [attr.aria-label]=\"resolvedAriaLabel()\" [style.height.px]=\"height()\">\n <!-- Named, where it was the only unnamed element in the component. The legend\n swatch is an `<svg>` too now, so `querySelector('svg')` no longer means\n \"the chart\" — and a plot that nothing can address by name is one a\n consumer's stylesheet and a spec both have to reach by position. -->\n <svg\n class=\"wr-line-chart__svg\"\n [attr.viewBox]=\"viewBox()\"\n preserveAspectRatio=\"none\"\n (pointermove)=\"onPointerMove($event)\"\n (pointerleave)=\"onPointerLeave()\"\n >\n @if (showGrid()) {\n @for (tick of yTicks(); track tick.value) {\n <line\n class=\"wr-line-chart__grid-line\"\n [attr.x1]=\"padding.left\"\n [attr.x2]=\"vbW - padding.right\"\n [attr.y1]=\"tick.y\"\n [attr.y2]=\"tick.y\"\n stroke=\"rgba(var(--wr-color-light-rgb), 0.7)\"\n stroke-width=\"1\"\n vector-effect=\"non-scaling-stroke\"\n />\n <text\n class=\"wr-line-chart__tick\"\n [attr.x]=\"padding.left - 6\"\n [attr.y]=\"tick.y + 4\"\n text-anchor=\"end\"\n fill=\"var(--wr-color-on-surface-muted)\"\n font-size=\"10\"\n font-family=\"var(--wr-font-family-base)\"\n >\n {{ formatTick(tick.value) }}\n </text>\n }\n }\n\n @for (s of resolvedSeries(); track s.label) {\n <path\n class=\"wr-line-chart__line\"\n [attr.d]=\"pathFor(s)\"\n fill=\"none\"\n [attr.stroke]=\"s.color\"\n [attr.stroke-dasharray]=\"s.dash || null\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n vector-effect=\"non-scaling-stroke\"\n />\n @if (showDots()) {\n @for (v of s.data; track $index; let i = $index) {\n <!-- A hole in the data gets no dot: the index still belongs to it, so the\n points after it stay on their own x. -->\n @if (v !== null) {\n <circle\n class=\"wr-line-chart__dot\"\n [attr.cx]=\"pointX(i)\"\n [attr.cy]=\"pointY(v)\"\n r=\"3\"\n [attr.fill]=\"s.color\"\n />\n }\n }\n }\n }\n\n @if (hovered !== null && hoverPoints().length > 0) {\n <line\n class=\"wr-line-chart__crosshair\"\n [attr.x1]=\"pointX(hovered)\"\n [attr.x2]=\"pointX(hovered)\"\n [attr.y1]=\"padding.top\"\n [attr.y2]=\"vbH - padding.bottom\"\n stroke=\"var(--wr-color-medium)\"\n stroke-width=\"1\"\n stroke-dasharray=\"3 3\"\n vector-effect=\"non-scaling-stroke\"\n />\n @for (p of hoverPoints(); track p.label) {\n <circle\n [attr.cx]=\"p.x\"\n [attr.cy]=\"p.y\"\n r=\"5\"\n fill=\"var(--wr-color-white)\"\n [attr.stroke]=\"p.color\"\n stroke-width=\"2\"\n />\n }\n }\n </svg>\n\n @if (hovered !== null && hoverPoints().length > 0) {\n <!-- The layer spans the plot and is what the tooltip's `cqw` measures. It is out of\n flow, so the containment it turns on costs the plot's own sizing nothing. The\n tooltip takes the same `--wr-line-chart-x` the x labels take, and the same clamp:\n centred on its point, never past either end. -->\n <div class=\"wr-line-chart__tooltip-layer\">\n <div\n class=\"wr-line-chart__tooltip\"\n [style.left.%]=\"xPercent(hovered)\"\n [style.--wr-line-chart-x]=\"xPercent(hovered)\"\n [style.top.px]=\"padding.top\"\n >\n <div class=\"wr-line-chart__tooltip-label\">{{ hoverLabel() }}</div>\n @for (p of hoverPoints(); track p.label) {\n <div class=\"wr-line-chart__tooltip-row\">\n <span class=\"wr-line-chart__swatch\" [style.background]=\"p.color\"></span>\n <span class=\"wr-line-chart__tooltip-name\">{{ p.label }}</span>\n <span class=\"wr-line-chart__tooltip-value\">{{ p.value }}</span>\n </div>\n }\n </div>\n </div>\n }\n</div>\n\n@if (xLabels().length > 0) {\n <div class=\"wr-line-chart__x-labels\">\n @for (label of xLabels(); track $index) {\n <!-- Each label hands the stylesheet two numbers, both percentages of the host's\n width — the space the stretching SVG is in, so they track the drawing at any\n size. The x of the point it names, which the stylesheet centres it on; and the\n widest it may be before it reaches a neighbour or the end of the strip, past\n which the stylesheet ellipsises it. Laying the labels out as equal centred flex\n slots instead is bar-chart geometry: only the middle label landed on its dot,\n and the outer ones sat up to half a column away. -->\n <span\n class=\"wr-line-chart__x-label\"\n [style.--wr-line-chart-x]=\"xPercent($index)\"\n [style.--wr-line-chart-x-max]=\"xMaxPercent($index)\"\n >{{ label }}</span\n >\n }\n </div>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -12,8 +12,9 @@ const SLICE_WIDTH = /(?:^|;)\s*width\s*:\s*([\d.]+)%/;
|
|
|
12
12
|
* Test harness for `<wr-meter-group>` — one bar divided into labelled bands.
|
|
13
13
|
*
|
|
14
14
|
* **The bar is a single `progressbar`, and its value is the TOTAL.** The bands
|
|
15
|
-
* themselves announce nothing: they carry a
|
|
16
|
-
*
|
|
15
|
+
* themselves announce nothing: they carry a hover tooltip (or, with `tooltip` off, a
|
|
16
|
+
* `title`) for a mouse and their share as an inline width, and the legend is where
|
|
17
|
+
* their labels and values are readable. So a
|
|
17
18
|
* spec that wants "how much of each" reads {@link getSlices} for the shares or
|
|
18
19
|
* {@link getLegendLabels} / {@link getLegendValues} for what is printed, and one that
|
|
19
20
|
* wants "how full" reads {@link getValue}.
|
|
@@ -62,7 +63,10 @@ class WrMeterGroupHarness extends ComponentHarness {
|
|
|
62
63
|
async getSlices() {
|
|
63
64
|
const slices = await this.locatorForAll('.wr-meter-group__slice')();
|
|
64
65
|
return Promise.all(slices.map(async (slice) => {
|
|
65
|
-
|
|
66
|
+
// `data-label`, which the band carries whatever `tooltip` says. The `title`
|
|
67
|
+
// this used to read is written only while the tooltip is off, so reading it
|
|
68
|
+
// would answer `null` for every band of a default meter.
|
|
69
|
+
const label = await slice.getAttribute('data-label');
|
|
66
70
|
return { label, percent: WrMeterGroupHarness.percentOf(label, await slice.getAttribute('style')) };
|
|
67
71
|
}));
|
|
68
72
|
}
|