iter(g223): 非档值按最近档对齐
This commit is contained in:
@@ -20,6 +20,13 @@ export function timePicker(props: TimePickerProps): HTMLElement {
|
||||
const minutes = Array.from({ length: Math.ceil(60 / step) }, (_, i) => pad(i * step)); // 00..55(按步长取)
|
||||
const picked = () => { const [hh = '', mm = ''] = value().split(':'); return { hh, mm }; }; // 拆分当前值
|
||||
|
||||
/*** 分钟档对齐:值不在步长档上(如 09:07 + 15 分钟档)时取最近档,作为高亮与滚动锚点 ***/
|
||||
const nearestMinute = (mm: string): string => {
|
||||
const n = Number(mm);
|
||||
if (!mm || Number.isNaN(n)) return ''; // 卫语句:没值或脏值不参与对齐
|
||||
return minutes[Math.min(minutes.length - 1, Math.round(n / step))] ?? '';
|
||||
};
|
||||
|
||||
/*** 写回时间:两段都补齐后调用回调;值未变时不重复派发(选时与选分各写一次) ***/
|
||||
const commit = (hh: string, mm: string): void => {
|
||||
const next = `${hh}:${mm}`;
|
||||
@@ -51,12 +58,13 @@ export function timePicker(props: TimePickerProps): HTMLElement {
|
||||
|
||||
/*** 造一列时间格:点击写回,激活格加 is-active 供样式与初始滚动定位 ***/
|
||||
const column = (label: string, list: string[], isHour: boolean) => {
|
||||
const activeText = () => (isHour ? picked().hh : nearestMinute(picked().mm)); // 本列该高亮的文案:分列按最近档对齐
|
||||
const cells = list.map((text) =>
|
||||
h('button', {
|
||||
type: 'button',
|
||||
class: () => `ua-timepicker-cell${(isHour ? picked().hh : picked().mm) === text ? ' is-active' : ''}`,
|
||||
class: () => `ua-timepicker-cell${activeText() === text ? ' is-active' : ''}`,
|
||||
role: 'option',
|
||||
'aria-selected': () => String((isHour ? picked().hh : picked().mm) === text),
|
||||
'aria-selected': () => String(activeText() === text),
|
||||
onClick: () => {
|
||||
const cur = picked();
|
||||
if (isHour) return commit(text, cur.mm || minutes[0]); // 先选时:分默认落到首个步长值,值立即可用
|
||||
@@ -129,9 +137,10 @@ export function timePicker(props: TimePickerProps): HTMLElement {
|
||||
if (open()) {
|
||||
releaseEsc ??= pushOverlay(() => { open(false); trigger.focus(); }); // 入 Esc 栈:与弹窗/抽屉共用逐层关闭
|
||||
requestAnimationFrame(() => {
|
||||
const now = new Date(); // 未选值时的锚点:打开就停在「此刻」附近,省得从 00:00 开始翻
|
||||
reveal(hourCol.col, hourCol.buttons, now.getHours());
|
||||
reveal(minuteCol.col, minuteCol.buttons, Math.floor(now.getMinutes() / step));
|
||||
const now = new Date(); // 无值时的锚点:打开就停在「此刻」附近,省得从 00:00 开始翻
|
||||
const { hh, mm } = picked();
|
||||
reveal(hourCol.col, hourCol.buttons, hh ? Number(hh) : now.getHours()); // 有值先滚到值上
|
||||
reveal(minuteCol.col, minuteCol.buttons, mm ? minutes.indexOf(nearestMinute(mm)) : Math.floor(now.getMinutes() / step));
|
||||
}); // 布局就绪后再量
|
||||
} else {
|
||||
releaseEsc?.();
|
||||
|
||||
@@ -3703,7 +3703,8 @@
|
||||
"列内可用 ↑↓ 环形移动、Home/End 直达首末;Tab、Esc、点击外部都能正常进出与收起",
|
||||
"需要 15 分钟一档就传 minuteStep: 15,步长只影响分列的可选值,时列始终 24 档",
|
||||
"需要允许回到「未选」态就传 clearable: true:有值时触发器右侧出现 ×(不进 Tab 序),聚焦触发器按 Delete / Backspace 也能清空,回调收到空串",
|
||||
"要和输入框并排对齐就传 size(sm / md / lg):高度走 --ua-control-h-* 三档,与 textField、select 的档位完全同源,不会出现「旁边的输入框矮 6px」"
|
||||
"要和输入框并排对齐就传 size(sm / md / lg):高度走 --ua-control-h-* 三档,与 textField、select 的档位完全同源,不会出现「旁边的输入框矮 6px」",
|
||||
"传入值不在步长档上时(如 09:07 + 15 分钟档)不会「没有高亮」:分列按最近档高亮并滚到位,点它即落到 09:15;原值在触发器上照常显示,直到用户重新选"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user