# DatePicker 日期选择器

日期选择器，支持 `date` / `daterange` / `month` / `monthrange` / `year` / `yearrange` / `datetime` / `datetimerange` / `week` / `quarter` 十种类型，键盘可操作，`Intl.DateTimeFormat` 格式化；触发器为输入框，可直接键入日期（失焦或回车提交，非法输入自动回退）。

## 基础选择

<DemoBlock title="基础用法（type=date）">
  <oas-date-picker value="2026-08-09" placeholder="请选择日期"></oas-date-picker>
</DemoBlock>

点击输入框展开日期面板，点击日期选中并关闭；也可直接键入 `2026-08-15`、`2026/8/15` 等形式后按 `Enter` / 失焦提交。

## 日期范围

<DemoBlock title="日期范围（type=daterange）">
  <oas-date-picker type="daterange" value='["2026-08-05","2026-08-15"]'></oas-date-picker>
</DemoBlock>

双月网格，先选起点再选终点，提交 JSON 数组 `["start","end"]`；悬停可预览区间。每次起止落选都会派发 `oas-calendar-change`（见[事件](#受控与事件)）。范围选择默认**双月网格**（左月 + 右月联动）；移动形态（窄屏抽屉面板）下双月网格纵向堆叠为单列，桌面容器不自动收缩为单面板。

## 月份与月份区间

<DemoBlock title="月份（type=month）">
  <oas-date-picker type="month" value="2026-08" placeholder="请选择月份"></oas-date-picker>
</DemoBlock>

<DemoBlock title="月份区间（type=monthrange）">
  <oas-date-picker type="monthrange" value='["2026-01","2026-06"]'></oas-date-picker>
</DemoBlock>

monthrange 值为 JSON 数组 `["yyyy-MM","yyyy-MM"]`，双年面板起止选月。

## 年份与年份区间

<DemoBlock title="年份（type=year）">
  <oas-date-picker type="year" value="2026" placeholder="请选择年份"></oas-date-picker>
</DemoBlock>

<DemoBlock title="年份区间（type=yearrange）">
  <oas-date-picker type="yearrange" value='["2024","2026"]'></oas-date-picker>
</DemoBlock>

年面板按 12 年一页翻动，值为 `yyyy`；yearrange 值为 JSON 数组 `["yyyy","yyyy"]`。

## 周与季度

<DemoBlock title="周（type=week，ISO 周值 yyyy-Wnn）">
  <oas-date-picker type="week" value="2026-W32" placeholder="请选择周"></oas-date-picker>
</DemoBlock>

<DemoBlock title="季度（type=quarter，值 yyyy-Qn）">
  <oas-date-picker type="quarter" value="2026-Q3" placeholder="请选择季度"></oas-date-picker>
</DemoBlock>

week 类型点击任一天即选中该天所在的整周（整行高亮 + 周号列）；quarter 面板为四格季度选择。

## 日期时间与时间范围

<DemoBlock title="日期时间（type=datetime）">
  <oas-date-picker type="datetime" value="2026-08-09T09:30:00"></oas-date-picker>
</DemoBlock>

<DemoBlock title="日期时间范围（type=datetimerange）">
  <oas-date-picker type="datetimerange" value='["2026-08-10T09:00:00","2026-08-20T18:00:00"]'></oas-date-picker>
</DemoBlock>

datetime 选日期与时分秒后点「确定」提交；datetimerange 双月 + 起止两组时间列，确定后提交 JSON 数组 `["yyyy-MM-ddTHH:mm:ss","yyyy-MM-ddTHH:mm:ss"]`。

## 范围分隔符

<DemoBlock title="separator 自定义范围分隔符">
  <oas-date-picker id="date-picker-separator" type="daterange" separator=" → " value='["2026-08-05","2026-08-15"]'></oas-date-picker>
  <oas-date-picker type="daterange" separator=" 至 " value='["2026-08-05","2026-08-15"]'></oas-date-picker>
</DemoBlock>

`separator` 自定义范围类型触发器内起止值的分隔符（缺省 `~`）；仅影响显示，value 契约不变。

## 范围默认时刻

<DemoBlock title="default-time（datetimerange 起止默认时分秒）">
  <oas-date-picker id="date-picker-default-time" type="datetimerange" default-time='["00:00:00","23:59:59"]' default-value="2026-08-15" placeholder="选起止日期后确定"></oas-date-picker>
  <oas-date-picker type="datetimerange" default-time='["09:00:00","18:00:00"]' default-value="2026-08-15" placeholder="工作时段 09:00-18:00"></oas-date-picker>
</DemoBlock>

`default-time`（`["起始时刻","结束时刻"]`，也支持单个 `"HH:mm:ss"` 起止同值）为 datetimerange 的起止时间列提供默认时刻：值为空或端点缺时间部分时自动补齐——`["00:00:00","23:59:59"]` 为常见整天区间惯例，选完日期点「确定」即得整天范围；快捷预设同样按此补时刻。未设置属性时内置惯例即为 `00:00:00` / `23:59:59`；值端点已带时刻时面板跟随已有时刻，不被覆盖。

## 触发器图标插槽

<DemoBlock title="prefix-icon / suffix-icon 插槽">
  <oas-date-picker id="date-picker-affix-icons" value="2026-08-09" style="margin-inline-end: var(--oas-space-4)">
    <oas-icon slot="prefix-icon" name="search"></oas-icon>
  </oas-date-picker>
  <oas-date-picker type="daterange" value='["2026-08-05","2026-08-15"]'>
    <oas-icon slot="suffix-icon" name="calendar"></oas-icon>
  </oas-date-picker>
</DemoBlock>

`slot="prefix-icon"` / `slot="suffix-icon"` 在触发器内分发前/后缀图标（装饰位：点击穿透到触发器开面板）。触发器文本自动让位；`clearable` 的清除钮与后缀图标同区，清除钮可见时后缀图标让位隐藏、清空后恢复。

## 禁用范围与导航边界

<DemoBlock title="min / max 限制">
  <oas-date-picker min="2026-08-01" max="2026-08-31" placeholder="仅可选 8 月"></oas-date-picker>
</DemoBlock>

越界日期不可选；同时翻页按钮到达 `min` / `max` 边界时置灰，不能再向外翻。

## 快捷预设

<DemoBlock title="快捷预设（shortcuts）">
  <oas-date-picker id="date-picker-shortcuts" value="2026-08-09"></oas-date-picker>
  <span id="date-picker-shortcuts-output" style="color: var(--oas-color-text-secondary); font-size: var(--oas-font-size-sm)"></span>
</DemoBlock>

`shortcuts`（property，`{ label, value }` 或 `{ label, getValue() }`），点击即应用并派发 `oas-change`、关闭面板。date / datetime / month / week / year / daterange / datetimerange / monthrange / yearrange 内置默认预设（标签走 locale）。

<DemoBlock title="预设侧栏（shortcuts-position=left）">
  <oas-date-picker type="daterange" shortcuts-position="left" placeholder="预设放左侧栏"></oas-date-picker>
</DemoBlock>

预设较多时可用 `shortcuts-position="left"` 将快捷栏改为面板左侧纵栏。

## 时区（timezone）

<DemoBlock title="timezone 时区锚点：纽约 vs 本地">
  <oas-date-picker id="date-picker-timezone-ny" timezone="America/New_York" placeholder="纽约时区：点开看「今天」" style="margin-inline-end: var(--oas-space-4)"></oas-date-picker>
  <oas-date-picker id="date-picker-timezone-local" placeholder="本地时区：点开看「今天」"></oas-date-picker>
  <span id="date-picker-timezone-output" style="color: var(--oas-color-text-secondary); font-size: var(--oas-font-size-sm)"></span>
</DemoBlock>

`timezone` 接受 IANA 时区名（如 `America/New_York`）或 `UTC`，缺省 / 非法值回落宿主本地时区。它只改变「何时算今天」与由此派生的默认值——面板中的「今天」高亮、「今天」快捷预设、`datetime` / `datetimerange` 的默认时刻推导都按指定时区的墙钟解释；`value` 契约（`yyyy-MM-dd` / ISO 时刻墙钟串）不变。打开左例面板可见「今天」外圈高亮落在纽约的当天，右例落在本地当天；下方对照行给出两个时区当前的日期。

## 禁用日期

<DemoBlock title="禁用过去日期（disabled-date）">
  <oas-date-picker id="date-picker-disabled-date" value="2026-08-09"></oas-date-picker>
</DemoBlock>

`disabledDate`（property，`(date: Date) => boolean`）返回 true 的日期置灰不可选（点击与键盘导航均跳过）；与 `min` / `max` 叠加禁用。

## 多选

<DemoBlock title="多选（multiple）">
  <oas-date-picker multiple value='["2026-08-09","2026-08-11"]'></oas-date-picker>
</DemoBlock>

`multiple` 时连续点选日期累加/取消，面板保持打开；值存 JSON 数组 `["yyyy-MM-dd", ...]`。

## 自定义格式

<DemoBlock title="format 自定义">
  <oas-date-picker value="2026-08-09" format="yyyy/MM/dd"></oas-date-picker>
  <oas-date-picker value="2026-08-09" format="MM月dd日 yyyy"></oas-date-picker>
</DemoBlock>

format 支持 `yyyy`/`MM`/`dd`/`HH`/`mm`/`ss` token（week / quarter 为固定值格式）。

## 面板能力

<DemoBlock title="双月独立翻页（unlink-panels）">
  <oas-date-picker type="daterange" unlink-panels value='["2026-08-05","2026-08-15"]'></oas-date-picker>
</DemoBlock>

范围面板默认双月联动翻页；`unlink-panels` 后左右两栏各自独立翻页（长区间跨年选择）。

<DemoBlock title="空值初始月锚定（default-value）">
  <oas-date-picker default-value="2026-08-15" placeholder="空值打开锚定到 2026 年 8 月"></oas-date-picker>
</DemoBlock>

无值时打开面板默认落在当前月；设置 `default-value` 后锚定到指定日期所在月（回显生日月份等场景）。

<DemoBlock title="标题月/年下拉（caption-layout=dropdown，出生日期快速跳转）">
  <oas-date-picker caption-layout="dropdown" default-value="1990-06-15" placeholder="选择出生日期"></oas-date-picker>
</DemoBlock>

`caption-layout="dropdown"` 把日面板标题换成**月 / 年两个下拉**（出生日期等远年场景免逐月翻页）：年下拉默认覆盖「今年-100 ～ 今年+10」（`min` / `max` 在场时收缩到边界年，越界月整月置灰），选择即跳转——**仅导航不改值**，选中日期仍由点击日格 / 快捷预设 / 手输提交。月 / 年标题顺序随 locale（zh 系年在前）；`type=date` / `datetime` / `week` 生效，其余类型（月/年/季度/范围面板自身已是块选择形态）保持标题按钮不变。键盘可用（原生 select），切换后焦点保持在下拉上可连续跳转。

<DemoBlock title="周号列（show-week-number）与周起始覆写（first-day-of-week）">
  <oas-date-picker value="2026-08-09" show-week-number first-day-of-week="0"></oas-date-picker>
</DemoBlock>

`show-week-number` 显示 ISO 周号列（`type=week` 自带）；`first-day-of-week`（0-6，0=周日）覆写周起始，默认跟随 locale。

## 单元格渲染

<DemoBlock title="日历标记（oas-cell-render / template[slot=cell]）">
  <oas-date-picker id="date-picker-cell-render" value="2026-08-09"></oas-date-picker>
</DemoBlock>

与 `oas-calendar` 同款双通道：`template[slot="cell"]` 克隆进每个日格（`[data-cell-date]` 自动绑定日期数字）；每个日格重建时派发 `oas-cell-render`，`detail: { date, element }`，宿主可追加徽标/价格等标记（监听须幂等）。

## 表单态

<DemoBlock title="尺寸（size）">
  <oas-date-picker size="small" value="2026-08-09"></oas-date-picker>
  <oas-date-picker size="medium" value="2026-08-09"></oas-date-picker>
  <oas-date-picker size="large" value="2026-08-09"></oas-date-picker>
</DemoBlock>

<DemoBlock title="校验态（status）与清除（clearable）">
  <oas-date-picker status="error" clearable value="2026-08-09" placeholder="error 态可清除"></oas-date-picker>
  <oas-date-picker status="warning" value="2026-08-09" placeholder="warning 态"></oas-date-picker>
  <oas-date-picker status="success" value="2026-08-09" placeholder="success 态"></oas-date-picker>
</DemoBlock>

`status=error` 联动 `aria-invalid`；`clearable` 在有值时显示清除钮，点击清空并派发 `oas-clear` + `oas-change`（空值）。

<DemoBlock title="只读（readonly）">
  <oas-date-picker readonly value="2026-08-09" placeholder="只读回显"></oas-date-picker>
</DemoBlock>

readonly 下面板可展开浏览、单元格可键盘导航，但点选 / 快捷 / 清除 / 手输均不提交。

## 受控与事件

<DemoBlock title="受控 + oas-change 事件">
  <oas-date-picker id="date-picker-event" value="2026-08-09"></oas-date-picker>
  <span id="date-picker-output" style="color: var(--oas-color-text-secondary); font-size: var(--oas-font-size-sm)"></span>
</DemoBlock>

<button id="date-picker-set" type="button" style="margin-top: 12px">设为 2026-08-20</button>

<DemoBlock title="受控开合（open + oas-open-change）">
  <oas-date-picker id="date-picker-open" value="2026-08-09"></oas-date-picker>
  <button id="date-picker-open-toggle" type="button">展开 / 收起</button>
</DemoBlock>

`open` 属性在场为受控模式：手势只派发 `oas-open-change`，开合由宿主增删属性决定。

<DemoBlock title="起止分步提示（oas-calendar-change）">
  <oas-date-picker id="date-picker-calendar-change" type="daterange" default-value="2026-08-01"></oas-date-picker>
  <span id="date-picker-calendar-change-output" style="color: var(--oas-color-text-secondary); font-size: var(--oas-font-size-sm)"></span>
</DemoBlock>

范围类型每次起止落选即派发 `oas-calendar-change`（`detail.value` 为 `[start, end|null]`），可做「已选起点」提示或动态换月。

## 禁用

<DemoBlock title="禁用（disabled）">
  <oas-date-picker disabled value="2026-08-09"></oas-date-picker>
</DemoBlock>

## 浮层定位（placement）

<DemoBlock title="右缘触发器（默认 bottom-start，自动翻转）">
  <oas-date-picker style="margin-left: auto; display: block; width: fit-content" value="2026-08-09" placeholder="贴右缘的单选"></oas-date-picker>
</DemoBlock>

<DemoBlock title="右缘宽面板（daterange 双月，自动翻转右对齐）">
  <oas-date-picker type="daterange" style="margin-left: auto; display: block; width: fit-content" placeholder="贴右缘的范围"></oas-date-picker>
</DemoBlock>

<DemoBlock title="显式 placement（top-end：上方弹出右对齐）">
  <oas-date-picker placement="top-end" value="2026-08-09" placeholder="placement=top-end"></oas-date-picker>
</DemoBlock>

<DemoBlock title="右缘宽面板（range 右对齐翻转）">
  <oas-date-picker type="daterange" style="margin-left: auto; display: block; width: fit-content" value='["2026-08-05","2026-08-15"]'></oas-date-picker>
</DemoBlock>

面板默认 `bottom-start`（面板左缘对齐触发器左缘）。触发器贴近视口右缘时自动右对齐翻转（`bottom-end`），右缘仍不足则水平夹取到视口内；下方空间不足时上翻（`top-start`/`top-end`）。`placement` 支持 12 向：`top / bottom / left / right` 各配 `-start` / `-end` 交叉轴对齐。

## 与 oas-calendar 的选择

弹层选择用 `oas-date-picker`（本组件，触发器 + 浮层面板）；筛选侧栏等常驻内嵌日历场景用 `oas-calendar`（纯面板形态，支持 `mode=year`、周号、单元格渲染等同族能力）。

## 移动形态（底部抽屉）

触屏（coarse pointer）或窄视口（<768px）下，面板自动改由 `oas-bottom-sheet` 底部抽屉承载：贴视口底升起 + 遮罩 + 拖拽把手下滑关闭（点遮罩 / Esc 同样收起），底部避让安全区；PC 形态保持原有浮层下拉不变。双月范围面板在窄屏自动收窄防横向溢出；抽屉内日格触控目标抬升至 44px（`--oas-touch-target-min`），触屏点选更易命中。

## required 必填

<DemoBlock title="required 必填（原生校验链）">
  <oas-date-picker required name="day"></oas-date-picker>
</DemoBlock>

`required` 驱动原生校验链（form-associated）：未填时 `checkValidity()` 为 false（`valueMissing`），原生表单提交被阻止；填写后自动恢复 `:valid`。

程序性读/写当前值走公开 `value` property：`el.value` 读取——等价 `getFormValue()` 语义的当前值（单值为 `value` 属性原串；`multiple`/范围模式为字符串数组，与 `oas-change` detail 同形）；`el.value = x` 写入——写受控 `value` 属性并即时回显 trigger（范围/多选传数组自动 JSON 序列化，空值移除属性），展开态面板选中态同步重锚，不派发事件。

## API

### oas-date-picker

#### 属性

| 属性 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| `caption-layout` | 面板标题形态：buttons（默认，标题按钮切月面板）/ dropdown（月/年下拉快速跳转，出生日期等远年场景；仅日网格单值面板 date/datetime/week 生效，选择仅导航不改值） | `string` | — |
| `clearable` | 可清除：有值时显示清除钮，点击清空并派发 `oas-clear` + `oas-change`（空值） | `boolean` | — |
| `default-time` | datetimerange 起止默认时刻（JSON 数组或单串同值；值缺时间部分时补齐） | `string` | — |
| `default-value` | 空值时面板初始锚点（如回显生日月份；有值时以值为锚） | `string` | — |
| `disabled` | 禁用 | `boolean` | — |
| `first-day-of-week` | 周起始覆写（0=周日 … 6=周六），默认跟随 locale | `string` | — |
| `format` | 展示格式 token（`yyyy`/`MM`/`dd`/`HH`/`mm`/`ss`；week/quarter 为固定值格式） | `string` | — |
| `max` | 可选范围（ISO 日期）；翻页到界时导航按钮置灰 | `string` | — |
| `min` | 可选范围（ISO 日期）；翻页到界时导航按钮置灰 | `string` | — |
| `multiple` | 多选（仅 `type=date`），值存 JSON 数组；该形态手输通道只读 | `boolean` | — |
| `name` | 表单字段名（原生 FormData 提交的 key；范围模式派生 name-start / name-end 两条 entry；无 name 浏览器自动不提交） | `string` | — |
| `open` | 受控开合：在场=展开、移除=收起；手势只派发 `oas-open-change` 由宿主回写；移动形态（触屏/窄视口 <768px）下展开态由 oas-bottom-sheet 底部抽屉承载（下滑/遮罩/Esc 收起），PC 为浮层下拉 | — | — |
| `placeholder` | 占位提示 | — | — |
| `placement` | 浮层位置，12 向：`top`/`bottom`/`left`/`right` × `-start`/`-end`（默认 `bottom-start`）；触发器贴近视口右缘时自动右对齐翻转、下方空间不足时上翻，并夹取到视口内 | `string` | `bottom-start` |
| `readonly` | 只读：面板可展开浏览（单元格可键盘导航），点选/快捷/清除/手输均不提交 | `boolean` | — |
| `required` | 必填标记（驱动原生校验链 valueMissing；不透传内层控件） | `boolean` | — |
| `separator` | 范围类型触发器内起止值分隔符（仅显示层，value 契约不变） | `string` | — |
| `shortcuts-position` | 快捷预设位置：`bottom`（默认，顶部横排）/ `left`（左侧纵栏） | `string` | `bottom` |
| `show-week-number` | 显示 ISO 周号列（`type=week` 自带） | `boolean` | — |
| `size` | 尺寸档：`small` / `medium` / `large`（就近读取 config-provider 注入） | `string` | `medium` |
| `status` | 校验态：`success` / `warning` / `error`（`error` 联动 `aria-invalid`） | `string` | — |
| `timezone` | 时区锚点：IANA 时区名（如 America/New_York）或 UTC；缺省/非法回落宿主本地。「今天」高亮、快捷预设与默认时刻推导按该时区墙钟解析，value 契约不变 | `string` | — |
| `type` | 类型：`date` / `daterange` / `month` / `monthrange` / `year` / `yearrange` / `datetime` / `datetimerange` / `week` / `quarter` | `string` | `date` |
| `unlink-panels` | 范围双月各自独立翻页（默认联动） | `boolean` | — |
| `value` | 当前值：`yyyy-MM-dd` / `yyyy-MM` / `yyyy` / `yyyy-Wnn` / `yyyy-Qn` / `yyyy-MM-ddTHH:mm:ss` / JSON 范围数组 | `string \| string[] \| null` | — |

#### Property（JS property；是否写回 attribute 见各行说明）

| Property | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| `disabledDate` | 禁用日期谓词（property 函数通道，`(date) => boolean`） | `((d: Date) => boolean) \| null` | — |
| `shortcuts` | 快捷预设（property 通道，`[{ label, value/getValue }]`） | `ShortcutItem[] \| null` | — |
| `value` | 当前值：单值日期串；范围 / 多选为字符串数组 | `string \| string[] \| null` | — |

#### 事件

| 事件 | 说明 |
| --- | --- |
| `oas-blur` | 组件整体失焦（组件内转移不误报） |
| `oas-calendar-change` | 范围类型起止落选即派发，`detail: { value: [start, end\|null] }`（宿主可做已选起点提示） |
| `oas-cell-render` | 日格重建时逐格派发，`detail: { date, element }`（标记点/徽标场景，监听须幂等） |
| `oas-change` | 值变化，`detail: { value }`（范围/multiple 为字符串数组） |
| `oas-clear` | 清除，`detail: { value }` 为清空前的值 |
| `oas-confirm` | datetime / datetimerange 点确定提交时派发（与 `oas-change` 并行），`detail: { value }` |
| `oas-focus` | 组件整体获焦 |
| `oas-open-change` | 开合变化，`detail: { open }`（受控/非受控均派发） |

#### 插槽

| 名称 | 说明 |
| --- | --- |
| `prefix-icon` | 触发器内前置图标（装饰位，点击穿透到触发器） |
| `suffix-icon` | 触发器内后置图标（清除钮可见时让位，清空后恢复） |
| `template[slot="cell"]` | `template[slot="cell"]` 克隆进每个日格，`[data-cell-date]` 自动绑定日期数字（与 `oas-cell-render` 双通道） |

#### CSS 变量

| CSS 变量 | 默认值 |
| --- | --- |
| `--oas-glass-blur` | `none` |
| `--oas-glass-ring` | `transparent` |

#### Property（快捷预设）

- `shortcuts`：快捷预设

键盘：`Enter` / `↓` 展开，方向键 / `Home` / `End` / `PageUp` / `PageDown`（`Shift` 换年）在网格内移动，`Enter` 选中，`Esc` 关闭。

<script setup>
import { onMounted } from 'vue'
onMounted(() => {
  const el = document.getElementById('date-picker-event')
  const out = document.getElementById('date-picker-output')
  const setBtn = document.getElementById('date-picker-set')
  el?.addEventListener('oas-change', (e) => {
    out.textContent = `oas-change: ${e.detail.value}`
  })
  setBtn?.addEventListener('click', () => el?.setAttribute('value', '2026-08-20'))

  // 受控开合（open + oas-open-change）
  const openEl = document.getElementById('date-picker-open')
  document.getElementById('date-picker-open-toggle')?.addEventListener('click', () => {
    if (openEl?.hasAttribute('open')) openEl.removeAttribute('open')
    else openEl?.setAttribute('open', '')
  })

  // 起止分步提示（oas-calendar-change）
  const cc = document.getElementById('date-picker-calendar-change')
  const ccOut = document.getElementById('date-picker-calendar-change-output')
  cc?.addEventListener('oas-calendar-change', (e) => {
    const [s, t] = e.detail.value
    ccOut.textContent = t ? `已选区间：${s} ~ ${t}` : `已选起点：${s}，请选择终点`
  })

  // 快捷预设（date）：静态 value + 动态 getValue
  const sc = document.getElementById('date-picker-shortcuts')
  const scOut = document.getElementById('date-picker-shortcuts-output')
  sc?.addEventListener('oas-change', (e) => {
    scOut.textContent = `oas-change: ${e.detail.value}`
  })
  sc.shortcuts = [
    { label: '今天', getValue: () => new Date() },
    {
      label: '明天',
      getValue: () => {
        const d = new Date()
        d.setDate(d.getDate() + 1)
        return d
      },
    },
    { label: '固定 2026-08-10', value: '2026-08-10' },
  ]

  // 禁用过去日期（disabled-date 走 property）
  const dd = document.getElementById('date-picker-disabled-date')
  dd.disabledDate = (d) => {
    const t = new Date()
    t.setHours(0, 0, 0, 0)
    return d < t
  }

  // 单元格渲染：模板经 JS 注入（内联 <template slot="cell"> 会被 Vue 编译管线吞空，dev 下尤甚），
  // 模板只提供日期数字骨架；标记点由 oas-cell-render 只给固定几天追加（幂等）
  const cr = document.getElementById('date-picker-cell-render')
  if (cr && !cr.querySelector('template[slot="cell"]')) {
    const tpl = document.createElement('template')
    tpl.setAttribute('slot', 'cell')
    tpl.innerHTML = '<span data-cell-date></span>'
    cr.appendChild(tpl)
  }
  const marks = new Set(['2026-08-10', '2026-08-20', '2026-08-28'])
  cr?.addEventListener('oas-cell-render', (e) => {
    const cell = e.detail.element
    if (marks.has(cell.getAttribute('data-date')) && !cell.querySelector('.cell-dot')) {
      const dot = document.createElement('span')
      dot.className = 'cell-dot'
      dot.setAttribute('role', 'img')
      dot.setAttribute('aria-label', '标记')
      cell.appendChild(dot)
    }
  })

  // 时区对照：把两个时区当前的日期写进对照行（与组件面板「今天」高亮同源，参照用）
  const tzOut = document.getElementById('date-picker-timezone-output')
  if (tzOut) {
    const dateOf = (tz) => {
      const opts = { year: 'numeric', month: '2-digit', day: '2-digit' }
      if (tz) opts.timeZone = tz
      return new Intl.DateTimeFormat('en-CA', opts).format(new Date())
    }
    tzOut.textContent = `今日：纽约 ${dateOf('America/New_York')} ／ 本地 ${dateOf(null)}`
  }
})
</script>
