-
SplitContainer(containers)修 分隔条拖一下就卡死:拖动起点记在build()的局部late double dragOrigin里,而每个DragUpdate都setState重建,GestureDetector会把在途识别器的回调就地换成新闭包——新闭包捕获的是本次构建的局部量,它的onDragStart永远不会被调用,于是第二个事件读未初始化的dragOrigin抛LateInitializationError: Local 'dragOrigin' has not been initialized。宿主表现是「键值浏览页上下两栏的分隔条只能拖约 10px,之后鼠标拖着走、栏不动」,异常只进日志不上屏。现在拖动起点(首块像素尺寸 + 指针全局坐标)记在 State 字段上,更新按绝对坐标算增量,重建换闭包不再影响在途拖动;同时补上onDragEnd/onDragCancel收尾(原先松手后起点状态残留)。回归测试见test/split_container_drag_test.dart(横 / 竖两向,分多次小步拖动要求累计位移与指针位移 1:1;另测拖过minFirst后反向拖能立刻跟手)。 -
DataGridView(lists)修 右键只弹菜单、不改选中:右键分支原先在onCellContext之后直接return,把选中逻辑留在了它后面,于是「右键落在哪个格」和「菜单作用于哪个格」是两件事——宿主菜单里的「置空 / 置为 NULL / 复制」跟着上一次的左键选区走,用户看着高亮框点右键,操作却打在别的格上。现在右键先让落点成为选中目标再弹菜单:落在选区外收缩为该单元格(行号列同理为该行为唯一选中),落在选区内保持整个集合不动,所以「置 NULL N 格 / 复制 N 行」这类批量口径不受影响。仍在同一条Listener.onPointerDown路径上完成,按下即生效、零延迟,也不触发onCellTap(右键不进就地编辑)。onCellContext的契约据此更新:宿主可直接读当前选中态来组织菜单项的单数/复数文案,不必自己补一次选中。 -
TabControl(containers)的TabItem新增可选tooltip:非空时标签头包一层WinToolTip(500ms 延迟,桌面悬浮习惯),鼠标悬停显示完整对象路径——宿主用它区分同名表(不同库 / 模式的organizations标签标题相同,只有悬浮才看得见表名 @ 库名(连接名)- 分类)。null/ 空 = 不显示,行为与旧版一致;包WinToolTip在 header 外层、不改标签宽度测量(_headerWidth只量 label),故纯标签条自适应排布不受影响。 -
新增
ImeSuppression(foundation /ime.dart,barrel 导出):一个宿主注入的关输入法钩子,Input在obscureText密码框获焦时调handler(true)、失焦时调handler(false)。base-ui 自身零平台代码,钩子默认null(不接线时行为与旧版逐字一致)。解决的是 Flutter/Windows 的硬伤:没有「按字段禁用系统输入法」的 API(open issue flutter/flutter#181487),中文输入法会把未上屏的拼音也塞进obscureText的圆点计数里——宿主实测「打bx显示三个点、回车上屏变两个点」,圆点数对不上真实输入、还弹候选窗。有了这个钩子,桌面宿主可把密码框获焦期间彻底关成裸字符输入。Input侧记住_imeSuppressed状态保证 suppress / restore 成对,并在dispose(获焦时窗口被关)补一次还原,避免输入法被永久解绑。回归测试见test/input_ime_test.dart。宿主接线见 darolib/app/ime_suppressor.dart+windows/runner的daro/ime通道(ImmAssociateContext)。 -
ToolStrip(menus)修 trailing 根本没钉在右缘:左侧按钮组用的是Flexible(fit: loose),而 loose 不吸收主轴余量,于是Row把空量留在末尾,trailing 仍紧贴按钮尾巴、整条右半空着(注释里承诺的「把 trailing 钉在右缘」从未发生)。改成Expanded后按钮组吃掉余量,trailing 真正贴右;按钮多到放不下时照旧横向滚动,不会撑爆报 overflow。回归测试见test/tool_strip_trailing_test.dart(窄按钮组时 trailing 与右缘对齐 / 12 个按钮不溢出)。 -
ExpandableSearch(form)展开态改为跟随外部 controller 的初始内容:controller.text非空时直接以输入框起步,不再恒从放大镜开始。宿主把过滤词存在跨页面存活的状态对象里(daro 的对象面板搜索:切去表数据页会让面板整棵子树销毁),旧行为是内容其实还在、却被藏进放大镜,看着就像「搜索被清空了」。不传controller时行为不变(自建空 controller → 收起态)。 -
ListPickerDialog(dialogs)按宿主参考工具(Navicat 表设计器「继承自」)的实测形状重做,由裸勾选清单改成带表头的单列网格:① 新增itemHeader(缺省名称)——列表上方一条secondaryColor表头,候选只有一列;② 行首加 16px「当前行」槽,打开时第 0 行为当前行,单击行即把 ▶ 移过去(Listener.onPointerDown,零延迟),勾选状态不受影响——点行=选行、点框=勾选,两套语义分开(原实现整行onTap即勾选,鼠标想确认看哪一行就顺手改了选择);③ 底部左侧新增 ↑ / ↓(IconBtn,边界行自动置灰),移动当前行;④ 确定后按当前行序回传,不再是候选列表顺序。第 ④ 条是行为变更而非装饰:调用方要的是「用户排出来的顺序」(INHERITS (父表…)就按这个顺序写),按候选顺序回传等于把 ↑↓ 白做。行渲染内置(不再走CheckedListBox),尺寸 / 配色全部仍从DesktopTokens取。回归测试见test/list_picker_dialog_test.dart。 -
新增
TextDiffView(data /text_diff_view.dart,barrel 导出):左右分栏的「之前 / 之后」逐行对比。diffTextLines(a, b)是顶层纯函数(先掐公共前后缀、中段跑 LCS,> 600 行退化为整段增删,避免打开页面卡在计算上),返回两侧行数相同的对齐行,故两栏共用一条垂直滚动、行高天然对齐;紧邻的「删除段 + 新增段」一对一配对成replaced,改动行在两侧同一行上同色,而不是左一条红杠右一条绿杠各说各话。配色按 token 派生并随明暗自适应(亮色加深、暗色提亮),空槽(该侧没有这一行)用中性灰与「有内容但没变」区分。宿主用它复刻参考工具(Navicat)视图设计器 SQL 预览的 DDL 对比页。回归测试见test/text_diff_view_test.dart。 -
新增
gridCellTokens(t)(lists /grid_metrics.dart,barrel 导出):表格与属性面板的紧凑尺寸档——fontSize ≤ 12、controlHeight ≤ 20、controlPaddingX ≤ 5(实测参考工具的设计器:行高 20.5、属性字段高 19.5、单元格文字左内边距 5)。与menuPanelTokens同一套约定:按 min 上限收,故幂等(宿主重复套不会越缩越小)、且用户把字号调得更小时保持用户的更小值;只动尺寸,不碰颜色。宿主用法是把整块区域包进TokenScope,区域内的Input/ComboBox一起落档,不必逐控件传height(ComboBox本来也没有height形参)。 -
ComboBox(common)两处: ① 新增showBorder(默认true):传false得到贴在宿主网格上的扁平单元格——不描边、不填底,文字直接落在网格线上。与既有Input.showBorder同一约定;daro 的表设计器网格静止态每格都不该有框,只有 1px 网格线。 ② 修每次重建都白造一整套候选项 widget:build()里无条件把items映射成DropdownMenuItem(每项一个Text)列表,而这份列表只有_buildEditable的一个从未使用的形参在收——即下拉没打开也在按选项数造 widget。宿主把设计器网格的类型列(40+ 个类型候选)做成常开编辑器后,这直接进到了每次敲字的重建成本里。现在随参数一并删除。 ③ 新增onTextChanged(仅editable模式生效):用户在输入框里敲字时回调原文。onChanged只在从下拉列表里选中一项时触发,手打的自由文本(如类型单元格里直接敲varchar(50))从不经它——需要留下用户输入值的宿主必须同时接这个,否则 typed 的值静默丢失。 -
CheckBox(common)新增size:方框边长,缺省仍是controlHeight * 0.5。宿主把行高压到 20 之后,按比例算出的方框只剩 10px,比参考工具实测的 13px 小一圈;勾选框是命中目标,不该跟着行高缩。 -
ToolbarButton(menus)两处: ① 新增paddingX(缺省compactSpacing * 2= 8)。纯图标按钮的点击块宽 = 图标 + 2 × 内边距,参考工具实测那一档是 25(14 图标 + 5.5 × 2);只给width不改内边距的话,内容固有宽 30 > 外框 25 会直接溢出报错。 ② 修tooltip与width互斥:Tooltip原先包的是内层 content,于是设了width的按钮一旦带 tooltip,定宽那层SizedBox就被丢掉、按钮退回内容宽。现在Tooltip包在最外层。 -
ToolbarButton(menus)新增filled/caretAtEnd/width,Popover(overlay)透传toggleOnTap:给「白底定宽下拉框 + 拆分按钮」用的三个正交开关。filled= WinForms ComboBox 的静态字段外观(backgroundColor白底、borderColor恒灰描边,hover / pressed 不变色不变底——下拉框是输入区不是按钮,跟随 hover 会误导可点性);caretAtEnd把尾部 ▾ 钉到控件右端、文本吃掉剩余宽度并省略号截断(需配合width,缺width时退化为普通间距,避免Spacer在无界宽度下抛断言);width固定总宽。Popover.toggleOnTap: false让触发区点击不再开合弹层、纯由controller驱动——拆分按钮(主体按下即执行、尾部小箭头单独开菜单,如 daro 查询页「▷ 运行 ▾」)需要这种分工,AnchoredOverlay早有此参数只是 Popover 没露出来。 -
Button(common)ghost 变体的聚焦态不再铺底色,只保留强调色描边。原先 ghost 聚焦会叠一层primaryColor14% 的浅蓝底,而宿主工具条 / ribbon 上「当前模式」的选中态通常是同一族浅色染色(daro 的 ribbon 用 accent 16% 叠control)——两档颜色肉眼几乎分不出,于是点了「新建查询」再切分类,同一排会出现两个看着都被点中的按钮。焦点是输入焦点、选中是状态,两套语义不能共用一种画法;现在聚焦只画一圈描边(Tab 键可达性不变),底色让给宿主的选中态。 -
TabControl(containers)标签条按 Navicat 实测重做溢出与配色: ① 新增pinnedCount——条首前 N 个标签排在滚动视口之外,永不随滚动位移(宿主用它钉住主入口页)。固定标签照常参与选中与键盘导航,_ensureVisible对它们直接跳过;判定「要不要出箭头」时先把它们的宽度从可用宽度里扣掉,否则固定块会被算进可滚动内容、标签稍多就误判溢出。 ② 修标签多到溢出时两个箭头一个都不出现(整条标签再也滚不到):两端可用性原先只挂在滚动监听上,而监听要等用户已经滚过才触发。现在溢出判定与两端可用性统一由测宽回调_syncScrollMetrics结算(滚动监听只刷新箭头),并且只要溢出就恒定画出两个箭头、滚不动的一侧置灰——按「能不能滚」决定显隐会让箭头在触底时突然消失,整条标签左右抽搐 24px。左箭头紧跟在固定块右侧,不摆到整条最左端。 ③ 滚轮压在标签条上即横向滚动(Listener.onPointerSignal,不必去够那对小箭头);键盘 / 右键菜单切到被裁掉的标签时自动_ensureVisible滚进可视区(延到下一帧,重排尚未完成)。 ④ 新增unselectedTabColor:未选中标签底色可显式钉死。缺省仍是「条底向surfaceColor提亮一档」,但宿主surfaceColor == background且要求白色标签条时,提亮结果会落在#FCFCFC~#FDFDFD这类近白上、整条发脏——纯白底必须直接传纯白。 ⑤ 底线不再叠成 2px:带正文的标签条由TabControl画一条横贯全宽的发丝线,未选中标签不再自画底线(_TabHeader.stripBottomLine);纯标签条没有那条全宽线,每个格子才自己补,否则一排标签悬在白底下沿全无交代。标签条底线与页面面板轮廓改用buttonBorderColor(比通用细线深一档)——面色是白的时候用borderColor会糊成一片,与 Button「面色变白后补回轮廓感」同一条规则。回归测试见test/tab_control_pinned_test.dart(固定标签不随滚动位移 / 不设pinnedCount时逐字节等价旧版 / 固定宽度不计入可滚动内容故不误判溢出 / 箭头格有顶边与底边)与test/tab_control_chrome_test.dart(纯标签条只给未选中标签画底线、带正文的标签条不重复画)。 -
日期时间选择器按 Navicat 重排,并把日历升级为三级快选: ①
MonthCalendar(dialogs)顶栏标题改为可点——日视图点标题进月份快选(4×3),月视图点标题进年份快选(12 年一档),再点回日视图;左右箭头按当前视图步进一档(月 / 年 / 12 年)。日格固定铺满 6 周,月外日子按参考图画成灰显且可点(选中该日并翻到所属月),底部补一行「今天: yyyy/m/d」图例。weekdayLabels参数取消,统一改走labels。 ② 新增TimeField(form):单行HH:MM:SS+ 右缘竖排上下按钮,替掉弹窗里「时 / 分 / 秒」三行NumericUpDown。三段各自可点为当前段(强调色底),上下按钮 / 滚轮 / ↑↓ 只作用在当前段并按 24 / 60 进制回环;← → 切段,Home / End 跳两端,数字键累加(装不下第二位时自动前进到下一段,拼不出合法值时以新数字重启该段),Backspace 退回上一段并清零。刻意不用TextField:IME 与选区会搅乱「哪一段是当前段」,而取值永远是定宽三段。 ③DateTimePickerLabels破坏性调整:去掉time/hour/minute/second(三行微调没了),新增today/monthNames/monthTitle/yearTitle/yearRangeTitle。三个标题是模板而非格式化函数({year}/{month}/{monthName}/{from}/{to}在渲染时由fill()替换),const构造因此仍然成立,中文'{year}年{month}月'与英文'{monthName} {year}'的语序差异各说各话。宿主侧注意:gen-l10n 的 ARB 不允许正文出现裸{}(会当占位符解析),故 daro 的 ARB 用[year]方括号书写、由宿主换成花括号。 ④ 三个弹窗(date / time / dateTime)改用共用的_PickerShell(264 / 200 定宽、controlColor底、compactSpacing * 2内边距)与居中的「确定 + 取消」动作行,与居中的「确定 + 取消」动作行,与参考图留白一致。回归测试见test/month_calendar_test.dart(三级下钻与回退 / 箭头按视图步进 / 邻月灰显日可点并翻月 / 区间把整月整年一起禁用)、test/time_field_test.dart(段命中 / 回环 / 累加前进 / Backspace / 滚轮 / 禁用态),以及test/inline_editor_date_picker_test.dart里新增的整弹窗用例(打开时显示值所在的月、标题下钻选月、TimeField 改分,确认后的合并值2022-03-25 20:14:06三项各自归位、未动的秒沿用原值)。演示页calendar.quickPickHint补了一句「点标题可快速选月 / 年」。 -
DataGridView(lists)新增可选横向虚拟化horizontalScrollController+horizontalViewportWidth:宽表把整个网格放进外层横向SingleChildScrollView时,每一行的Row原先会把所有列都建成真实 widget(哪怕横向滚出视口),于是「勾选列 / 选择 / 拖拽改列宽」等任何触发网格重建的操作,成本 ∝ 可见行 × 全部列(daro 表数据页 21 列 × 约 36 行 ≈ 750 格 / 帧,勾选时肉眼可见掉帧)。同时传入横向滚动控制器与视口宽后,数据行只渲染与视口相交的列,用左右占位条撑出等宽(横向滚动范围、_colAtX命中测试、选中坐标均不受影响),把每帧重建量降到 ∝ 可见行 × 视口内列。默认关闭——不传这两个参数时逐字节等价于旧版,表头始终整行渲染(列宽调整 / 排序手柄需常驻,且仅 1 行成本可忽略)。回归测试见test/data_grid_hvirtual_test.dart(视口外列不建 widget / 横向滚动换窗 / 换窗后点击命中正确列 / 行号列随内容滚出 / 无视口宽回退整行)。 -
Input(common)修字段内按钮点不动:trailing(行内编辑器的日历/时钟按钮)与obscureToggle(密码眼睛)此前直接挂在Row里,落在TextField自带的TextFieldTapRegion之外——按下那一下被EditableText判成「点到框外」,默认行为是直接失焦。宿主只要把「失焦」当提交(InlineEditor就是),编辑器会在抬起之前被拆掉,按钮的onTap永远收不到,表现为「点日历没反应」。表格里按下必然伴随宿主选中重绘(多出一帧),所以只在单元格内稳定复现、单独摆一个编辑器反而正常。现在两者都包进TextFieldTapRegion,与输入框同属一个点击区。回归测试见test/inline_editor_date_picker_test.dart(按下 → 渲染一帧 → 抬起的真实节奏下弹窗照常打开、且不触发失焦提交;去掉包装即红)。 -
新增
buildTextBoxContextMenu(context, editable, {tokens})(menus)与ContextMenuPanel:Input的右键菜单不再用 Flutter 自带的 Material 选择工具条(圆角浮层 + 图标按钮,和全库的 Win10 菜单不是一套),改走本库面板渲染。剪切 / 复制 / 粘贴 / 全选恒定列出,当前做不了的置灰而不是隐藏(可用性仍取自EditableTextState.contextMenuButtonItems,它才知道只读框不能粘贴、无选区不能复制),快捷键标在右缘,菜单左上角落在鼠标按下处并在屏幕边缘折回;标签取MaterialLocalizations(cutButtonLabel等,因此跟随宿主语言),动作与收起都交回EditableTextState(onPressed/hideToolbar)。粘贴项可用性依赖异步回来的剪贴板状态,故面板包一层ValueListenableBuilder(clipboardStatus),状态到达后自动从置灰变可用。ContextMenuPanel是从showContextMenu抽出的面板本体(边框 + 条目列,不含定位与点击外部关闭的屏障),两处共用同一套绘制。回归测试见test/text_box_context_menu_test.dart(弹的是本库面板且四项全在 / 点「全选」真的全选并收起;去掉contextMenuBuilder即红)。 -
ScrollBar(scroll)新增notificationPredicate(透传给 Material Scrollbar):修纵向条挂在横向滚动区外面时整条不显示。Material 的 Scrollbar 默认只接收depth == 0的滚动通知,宽表网格的标准摆法(纵向条包住横向SingleChildScrollView,内层再放纵向 ListView)中,内层通知冒泡经过横向 Scrollable 会被记为 depth 1、全被默认过滤器拒收,纵向条因永远拿不到尺寸而不绘制。宿主传notificationPredicate: (n) => n.metrics.axis == Axis.vertical按轴过滤即可。回归测试见test/scroll_bar_test.dart(嵌套结构下断言右缘画出轨道/滑块矩形;去掉 predicate 即红)。 -
DataGridView(lists)单元格内容改为在列内居中:column.alignment此前是把整格包一层Align,右对齐列的容器会按文字宽度收缩——竖向网格线和选中底色跟着文字走而不是贴着列缘;且默认centerLeft分支根本不包,文字被拉成整行高并贴着行顶(行高一密就明显看出没居中)。现在对齐落在装饰容器内部的Align上,容器恒占满列宽,两个轴都由column.alignment说话(数值列传Alignment.centerRight)。编辑态不受影响(编辑器仍撑满整格)。回归测试见test/data_grid_cell_alignment_test.dart(左/右对齐的文字中线与单元格中线重合、右对齐列容器仍等于列宽)。 -
Input(common)新增height:控件高度,缺省仍取controlHeight(28)。表格行做密集后(22px)行内编辑器会撑破行——原先Input把高度写死成令牌值,宿主无法压低;现在内部垂直留白按此高度推导(contentPadding为自定义值时只追加垂直分量,横向仍归宿主)。InlineEditor(form)随之将自身height透传给Input,并新增textAlign:数值列右对齐时编辑态与显示态同向,Enter 进编辑文字不跳位。 -
CheckBox(common)勾选态改为实心:选中 =primaryColor填充 +accentForegroundColor白色勾号 + 3px 圆角,未选中仍是描边空框,禁用勾选为controlDisabledColor底 + 禁用勾号。原「透明底 + 边框 + 前景色勾号」的传统 WinForms 画法在密集列表(字段勾选、导入候选)里视觉重量太低,扫读时不易分辨勾没勾。配套:CheckedListBox(lists)此前违规直接使用 MaterialCheckbox自绘实心样式,现改为复用本组件(onChanged置空 = 被动指示器,点击仍由整行onTap结算,无双切换手),全库勾选框收敛为一种画法。 -
TreeView(lists)新增rowBuilder与framed:前者让宿主接管行内容(图标 / 次级灰字后缀 / 徽标这类内置「一行一个标签」画不出来的行),行盒的高度、缩进、命中区仍由组件负责,宿主通过TreeRowContext拿到depth/selected/expanded/hasChildren/tokens和toggleExpand;提供rowBuilder时组件不再绘制实心强调色选中底(自带图标与次级文字的行通常要的是浅色染色 + 描边,实心蓝会把图标吞掉),不传时行为与旧版逐像素一致。framed: false去掉外框与底色,供宿主面板自身已经有边框 / 内边距时使用(原先这类场景只能把边框留在那里叠成双线)。典型用法见 daro 的 PostgreSQL 依赖页(「使用 / 被使用」:schema.name+ 灰色KIND (DEGREE)+ 外键下挂内部触发器子项)。 -
日期时间选择弹窗改为可独立复用的入口:新增顶层
showDateTimePickerDialog(context, {mode, value, minDate, maxDate, labels}),返回确认后的DateTime?(取消为null)。DateTimePicker自身的三种模式全部改走该入口,三个私有弹窗从「外部可变闭包 + 回调」改为Navigator.pop(结果),宿主想在自己的字段右缘挂一个「…」选择按钮时可直接调用,不必复制弹窗结构。合并规则不变:date只换日期保留时间、time只换时间保留日期。 配套:① 新增DateTimePickerLabels(ok/cancel/time/selectTime/hour/minute/second/weekdayLabels),库内默认英文,宿主按ComboBox.searchHint的同一约定传自己语言的文案;DateTimePicker新增labels字段。②MonthCalendar新增weekdayLabels(周一开头 7 项,null用内置Mo…Su)——星期表头原先写死在 State 里,中文宿主无法本地化。③ 修time模式丢失已有秒数:_TimePickDialog的秒固定从0起算(只取了TimeOfDay的时/分),确认后把原值的秒清掉了;现在初值直接收DateTime,秒沿用。另导出formatDateTimeByMode(dt, mode)与parseDateTimeField(text)(接受2022-12-12 20:13:06这类带空格、DateTime.tryParse不认的库内格式),供宿主做「文本 ↔ 值」往返。裸时间20:13:06也认(锚到今天,只为取回时分秒),否则time列一打开就掉到当前时刻。 另修一处实测缺陷:日历原先永远开在当前月——_DatePickDialog/_DateTimePickDialog只传selectedDate不传displayMonth,MonthCalendar于是回落到DateTime.now();编辑一个 2022 年的值,弹层显示的是当前月,选中日既看不见也点不到,随手点「确定」还把年份改掉了。两处现在都传displayMonth: 选中值。回归测试见test/inline_editor_date_picker_test.dart。 -
Input新增trailing(common):渲染在边框内右缘的附加控件(「…」浏览、日历按钮这类字段内动作),与密码obscureToggle的眼睛可共存(眼睛在前、trailing 最右);两者都为空时渲染结构与旧版完全一致。InlineEditor(form)据此新增datePickerMode/datePickerLabels:传入模式即在字段右缘挂一个日历(date/dateTime)或时钟(time)按钮,点击弹出showDateTimePickerDialog,确认后按该模式的默认格式写回文本(yyyy-MM-dd/HH:mm:ss/ 两者),onChanged照常触发,Enter / 失焦提交与 Esc 取消语义不变。关键守卫:弹窗会抢走焦点,原先「失焦即提交」会在打开弹窗那一刻带着旧文本结算掉编辑器,故新增_picking标记,选值期间的失焦不算离开编辑器,弹窗关闭后把焦点还给输入框。 -
LinkLabel(common)新增underline(默认true,行为与旧版一致):可关掉下划线,只保留链接色。桌面详情面板(如 Navicat 的库 / 表信息页)把「共享」这类动作渲染成蓝色文字但无下划线,硬编码的下划线会让它和同排的普通文字抢视觉重量。取色与禁用态不变(primaryColor/disabledForegroundColor),hover 手型也保留——去掉下划线不改变它是可点的。 -
Surface(common)去掉 hover / pressed 的 120ms 颜色渐变(AnimatedContainer→Container)。未选中态底色是transparent(即0x00000000,RGB 通道为 0),向浅灰插值时通道会先经过半透明的深灰——鼠标进入一个无边框 / 透明底的可交互面(Toggle、菜单行、列表行)会看到「先黑一下、再变浅」的两段跳色,而不是直接落到悬浮色。顺带符合本库的快节奏约定:悬浮反馈无动画(WinForms 语义)。所有以透明为常态底色的组件同时受益,无需各自绕路。 -
Toggle(common)新增ToggleVariant.ghost:与default_一样无边框,但选中态取outline的淡强调色染色(accentColor16% 压在controlColor上)而非实心强调底,前景保持主文字色——供「图标 + 文字」这类自带颜色的开关使用,实心蓝会把图标线稿的蓝色强调吞掉。多个ghost开关紧邻排列即为工具条分段样式。未选中态的悬浮底色同时从mutedColor改为controlHoverColor(winForm 预设#E1E1E1):mutedColor(#F4F4F4) 是行号槽那类近白底色,悬停在纸白工具条上几乎看不出来。回归测试见test/modern_components_test.dart(hover 一帧内落定悬浮色 / ghost 选中染色且无边框)。 -
ComboBox(common)新增searchable(默认false):只读下拉的面板顶部多一条搜索行(放大镜 + 单行输入,文案走searchHint/noMatchText,缺省英文、中文由宿主传入),输入即按itemToString做大小写不敏感的子串过滤,无匹配时留一行占位文案(面板不塌)。输入只是过滤、不是取值 —— 这一点与editable(允许提交items之外的自定义值)刻意分开:连接 / 库 / 模式这类「值必须来自列表」的选择器可以放心开输入搜索,敲错的查询永远提交不上去(Enter 取第一个匹配项,Escape 关面板,面板每次打开都从「无筛选」开始)。面板高度随过滤结果收缩(最多 10 行),搜索行严格等于controlHeight、由独立一层 1px 分隔线收口。 同时修掉两处面板刷新缺陷(旧代码里都存在):① 候选列表 / 选中下标原先在_buildOverlayEntry里捕获,而OverlayEntry刷新时只重跑自己的 builder —— 过滤与 hover 高亮都会拿着「打开那一刻」的旧值不放(症状就是输入没反应、鼠标划过不高亮),现在一律在 builder 内现算,刷新统一走markNeedsBuild;② 面板外层Container的decoration边框会被Container当作内边距用,子项可用高度比maxHeight少掉两条边框 —— 一旦把列表换成固定高度就稳定溢出 2px,故去掉constraints(各行高度本就算死,不需要兜底)。回归测试见test/widgets_test.dart(输入窄化列表 / Enter 取首个匹配 / 无匹配查询绝不提交 / 只读模式无搜索行)。 -
TabControl标签头改为按内容自适应(对齐 Navicat 的紧凑标签条):高度 = 标签行高 +compactSpacing * 0.75 * 2+ 边框(winForm 令牌下未选中 20.65 / 选中 23.65,Navicat 实测 20.5 / 23),宽度 = 实测文本宽 +compactSpacing * 2 * 2(下限compactSpacing * 11= 44)。barHeight/tabWidth只在调用方显式传参时才固定宽度/高度,原先各宿主硬编码的 24/26/30/32 与 56/62/72/76/82/96 一类数字全部可以删掉 —— 长度不一的标题(「消息 / 结果 1 / 结果 12」)不再被压成省略号,短标题也不再白占一整格。测量文本必须用DefaultTextStyle.of(context).style.merge(标签样式):Material 的默认文本样式带letterSpacing,拿裸TextStyle量会偏窄、长标题被压成省略号;可关闭标签(TabItem.onClose)在自动宽度里额外预留 20px 关闭按钮位(按钮 hover 才出现,不预留会挤掉文案)。新增TabControl.stripHeight(tokens)静态入口,供宿主计算「标签条 + 页面面板」占掉的高度 —— 对话框里原先硬编码的_kTabChromeHeight = 32之类已无必要(组件度量一改就会静默错位)。 -
TabControl标签条 chrome 修正:每个标签都画顶边 + 右侧 1px 分隔线,但左边线只在「标签条与正文构成闭合框」时才画(drawLeftEdge = hasBody && i == 0,供对话框封左边框);纯标签条场景(所有TabItem.child为null,如文档标签条)不画 —— 它悬在背景上,画出来就是面板左边框旁凭空多出一条 1px 竖线。未选中标签底色 = 向surfaceColor提亮 22%。 -
DesktopTokens新增按钮专用令牌组:buttonHeight(默认 24)/buttonMinWidth(默认 73)/buttonFaceColor/buttonBorderColor/buttonHoverFaceColor/buttonHoverBorderColor/buttonPressedFaceColor/buttonPressedBorderColor(winForm 与 shadcn 两版预设均已给值)。刻意与controlHeight(28) 分离:桌面工具包的按钮总比单行编辑框矮一档(Navicat 实测按钮 73×24、输入框高 19.5),改按钮不应连带改到输入框 / 下拉 / 复选。Button的solid变体接入:常态面取buttonFaceColor、边取buttonBorderColor(比通用控件边线略深一档,补回面色变白后丢掉的轮廓感);hover / pressed 走专用热态令牌,规则是「染强调色」而不是「把中性面色压暗」—— 后者只能叠出灰,越悬停越脏,参考图实测悬浮面 #E0EEF9 + 边 #0078D4、按下再深一档。下边框恒比上 / 左 / 右暗 ~10.5%(桌面按钮 VCL/Aero 的 3D 下缘;参考图常态 #D0D0D0→#BABABA、悬浮 #0078D4→#006BBE 同一比例),由Color.alphaBlend(0x1B000000, 边色)组件内现算,不另加令牌。只有child == null的纯文字按钮吃buttonMinWidth(桌面对话框把「确定 / 取消 / 上一步」摆在等宽按钮列上,不会贴着字收紧);带child的工具条 / 图标按钮一律按内容自适应,否则窄工具条会被 73 撑破。ghost/primary变体与禁用态外观不变。 -
新增
DesktopTokens.withHairlineBorders(BuildContext context):把borderWidth按1 / devicePixelRatio收窄(下限 0.25),使边框恒定占 1 设备像素。参照物是原生窗口(Navicat / VCL),其边框恒为 1 物理像素、与显示缩放无关,而令牌里的borderWidth = 1.0是逻辑像素 —— 200% 缩放下会画成 2 物理像素,比原生窗口粗一倍(实测 daro 截图描边占 2 物理像素、Navicat 占 1)。单 DPI(100%) 下返回 1.0,行为与改前完全一致,只有高 DPI 屏才变。拿不到MediaQuery时原样返回。 -
组件里不再写死线宽:
CheckBox的方框、MarqueeSelector的选框、StepBar的连接线(Container(height: 1))、ThemeDesigner导出页输入框的描边,原先分别写死width: 1/height: 1,改为取t.borderWidth。这些在 200% 屏幕上会明显比周围边框粗,且不收窄的话「1 设备像素边框」策略对它们无效。 -
DialogBox底部动作条改为浅灰带:底色取secondaryColor、上方 1pxborderColor分隔线、内边距 10/9(Navicat 实测),整条铺满对话框宽度(内边距由Container提供,浅灰底一直顶到对话框边框)。按钮面色朝纸白、压在浅灰条上,层次才出得来 —— 此前按钮与正文同底色,只靠一条空隙分隔,整块读起来是平的。 -
新增
ThresholdDraggable(lists):只有真的拖了才起手的Draggable。框架Draggable有两条「没拖就先起手」的路径,桌面端单击 / 双击都会闪拖拽特效:① 竞技场默认接受——本识别器是竞技场唯一成员时(桌面端鼠标点一个拖拽源通常就是这种情况,Scrollable的拖拽识别器默认不接受鼠标),GestureArenaManager.close()直接把这一手判给它,onDragStarted在 pointer down 的微任务里就触发了,指针一寸没动而浮层预览、childWhenDragging与宿主据此点亮的放置区已全部出现,松手再收回;② 鼠标起手容差只有 1px——框架对鼠标硬编码kPrecisePointerHitSlop(只有触屏 / 触控板才读MediaQuery.gestureSettings.touchSlop),单击 / 双击时几像素手抖即可判定成拖动。典型症状即「双击打开一行却闪出拖拽浮层」。本组件把阈值提高到startSlop(默认kDragStartSlop= 4px,与 Windows 的SM_CXDRAG及本库MarqueeSelector.threshold同量级),并把「竞技场判给本识别器」与「起手」分开:输了手势竞争不算,赢了但位移没到阈值也只挂起起手回调,位移够了才真正起手、不够就作废(不闪浮层、不触发onDragStarted)。按下即拖的手感不变(不引入LongPressDraggable那种时间延迟),位移累计值在真正起手时一次性补报给浮层,拖起来不跳。构造函数逐字段对齐Draggable,可直接替换。配套导出ThresholdMultiDragGestureRecognizer(affinity一个字段覆盖任意 / 水平 / 垂直三个方向,宿主用自己的RawGestureDetector时可直接用)。回归测试见test/threshold_draggable_test.dart(唯一成员时单纯按下不起手 / 鼠标 3px 手抖不起手 / 位移跨过阈值才起手并落到DragTarget/ 有竞争识别器时同样成立)。 -
DataGridView(lists)行号列右键不再改选中:此前_buildRowNumberCell的Listener.onPointerDown对左 / 右键一视同仁先触发onRowSelected再在右键时补发onCellContext,导致右键一行会先把多行选中打散成单选,与数据单元格「右键只弹菜单、不动选中」的语义不一致。现改为右键分支直接return,仅左键(含 Ctrl / Shift 修饰)走onRowSelected。宿主读修饰键做多行加 / 连选时不再被右键意外重置。 -
DataGridView(lists)新增selectedRows(Set<int>?):多行选中渲染。集合非空时接管行底色与行号列选中态(rowNumberBuilder的rowSelected参数),此时selectedRow被忽略。指针语义不变:onRowSelected仍只回传点击行号,宿主自行读修饰键(Ctrl 加选 / Shift 连选)更新集合并回传,符合「行为归宿主、绘制归组件」的既有分工。用于表数据浏览页像 Navicat 那样多行选中 + 复制 / 粘贴 / 删除。缺省null与旧版一致,既有调用零影响。 -
DataGridView(lists)拖拽框选补上纵向滚动偏移:跟踪指针的Listener包在ListView外层,其localPosition.dy是视口坐标,而_rowAtY直接dy ~/ rowHeight当成绝对行号 —— 一旦滚动过(含框选到边缘触发的自动滚动),选中的是「可见第几行」而不是指针所在的行(纵向偏移越大错得越多,自动滚动时选区还会反向收缩)。现统一加上verticalScrollController.offset。横向无需处理:该Listener本身在外层横向视口的内容坐标系里。回归测试见test/data_grid_region_select_test.dart。 -
DataGridView(lists)框选模式下onCellTap改在抬起且未发生拖拽时触发:此前它挂在单元格的onPointerDown上,而Listener模式下选中与「进入就地编辑」必须分家 —— 按下就开编辑器,随后拖出的框选会和一个正在抢焦点的输入框打架。现在按下只更新选中集合(零延迟不变),抬手时若确认没拖动才补发onCellTap,宿主可放心在此进入编辑;框选 / 拖拽收尾不会误开编辑器,onPointerCancel同样不发。未传onCellsSelected的调用方行为完全不变。 -
InlineEditor(form)新增selectAll(默认false):进入编辑时全选初始文本,供节点内联改名等「键入即覆盖」场景使用;true时 controller 预置全选区并同步Input.selectAllOnFocus。默认值下行为与旧版完全一致(光标置于文本末尾),既有调用零影响。 -
修复
Button(common)禁用态吞掉父级点击:onPressed == null时onTap/onTapDown/onTapUp都已置空,唯独onTapCancel仍无条件注册,于是TapGestureRecognizer照样进入竞技场、并因层级比父级更深而胜出——父级收不到这次点击,按钮自己又什么都不做。现在 disabled 时四个点击回调全为null,按钮彻底不注册识别器,包裹它的父级触发器(Sheet/Command的trigger: Button(...))恢复可用。与 WinForms 一致:禁用控件不吞鼠标消息。回归测试见test/widgets_test.dart(禁用按钮点父级仍触发)与test/modern_components_test.dart(SidePanel / Command 经禁用 trigger 打开)。 -
新增
TabStrip(containers):扁平下划线标签条(浏览器 / Navicat 面板内子标签样式,如设计器「更改 / DDL」切换),TabControl的轻量对应物。受控组件:宿主持有index、响应onChanged;选中项 =primaryColor文字 + 2px 下划线 + 内容底色衬底,未选中项 hover 淡底。切换走onTapDown(按下即触发,零延迟,不注册双击手势),零动画、无 Material 水波纹,取色链tokens ?? TokenScope.maybeOf ?? DesktopTokens.winForm。 -
新增
InputDialog(dialogs):单行文本 / 密码录入弹窗(「连接需要密码」这类打开前补录凭据的 WinForm 对应物)。由DialogBox+Input+Button组合,show回传输入文本,取消 / 关闭 / Escape 回传null。password: true时输入框走obscureText+ 眼睛切换,且空输入禁用确定——调用方可契约式假定非 null 结果必非空;message为输入框上方的提示文本,initialValue预填,okText/cancelText缺省OK/Cancel(中文由宿主传入)。Enter 提交、零动画、无 Material 水波纹,取色链tokens ?? TokenScope.maybeOf ?? DesktopTokens.winForm。 -
MessageBox(overlay)底部按钮区调整:去掉正文与按钮之间的Separator分割线,按钮行由右对齐改为居中。按钮顺序、自动聚焦(主按钮)、间距均不变。 -
滚动条改为静止窄条、悬浮加宽:
ScrollBar由无状态改为自绘热区检测——MouseRegion监听滚动条贴边一带(宽度 = 悬浮态宽度 + 4px),鼠标进入即把传给Scrollbar.thickness的宽度从 5px(kScrollBarSlimThickness)切回 8px(kScrollBarExpandedThickness,可用thumbThickness覆写,零动画即时切换)。不再依赖 Material 内部的悬浮WidgetState(实测其在部分场景不可达)。同时新增scrollbarHoverThickness():按WidgetState.hovered / dragged切换厚度的WidgetStateProperty,供宿主写入全局ThemeData.scrollbarTheme.thickness,让 Flutter 默认滚动行为为普通ListView/ScrollView生成的滚动条也走同一策略。thumbThickness语义变为「悬浮态宽度」。回归测试见test/scroll_bar_test.dart(纵向/横向悬浮、自定义宽度、状态解析器)。 -
CheckBox的onChanged改为可选(common):字段本就是ValueChanged<bool?>?,仅构造器标了required。传null即渲染一个被动的勾选指示器——视觉与可交互态完全一致(边框仍取foregroundColor,禁用仍走enabled),只是不注册 tap / 键盘处理。用途:勾选框位于DataGridView单元格里时,外层单元格的GestureDetector(onDoubleTap)会把勾选框自身的onTap扣在约 300ms 的双击判定窗口里,单击看起来「没反应」;宿主改用Listener.onPointerDown在按下瞬间结算勾选,CheckBox只负责显示状态。既有调用全部不受影响。 -
Toggleoutline变体的选中态改浅:不再填充实心accentColor,改为accentColor(16% alpha)叠加在controlColor上的淡色染色 +accentColor描边,文字 / 图标前景保持foregroundColor(不再换成accentForegroundColor)。原因:宿主工具面板标签是「黑色线稿 + 蓝色强调」的自绘图标,实心蓝底会把图标里的蓝色部分整个吞掉。default_变体(加粗 / 斜体这类纯色图标工具栏按钮)仍是实心 accent 填充 + 反色前景,行为不变;outline未选中态也完全不变。 -
Button新增ButtonVariant.primary(common):对话框 / 面板里唯一主操作的实心强调色按钮(确定、应用、保存)。底色primaryColor、文字accentForegroundColor,禁用时两者各降不透明度(0.45 / 0.6)而非换成灰色面;描边与底色同色(纯色块无边界感),仅在聚焦时换成foregroundColor描边。hover / pressed 仍走叠加色,但因hoverOverlayColor在实心色底上几乎不可见(约 4% 黑),两级都改用pressedOverlayColor叠加——hover 一层、按下两层,保证快节奏下反馈可辨。零动画、无 Material 水波纹,按下不抢焦点、完整点击才聚焦(与solid同一套焦点时机)。默认值不变,既有调用零影响。 -
DataGridView表头支持两行标题:DataGridViewColumn新增subtitle(第二行文本,如列数据类型)与subtitleGlyph(副标题前的 accent 色小字形,如#/abc)。任一列带副标题时表头整体加高 14px 并切换为两行布局(标题行 + 14px 副标题行,无副标题的列第二行留空保持对齐);副标题字号比headerFontSize小 1.5px、取mutedForegroundColor。全部列都不带副标题时高度与渲染与旧版完全一致,既有调用零影响。排序箭头仍位于标题行右侧。 -
DataGridViewColumn新增subtitleIcon(IconData?):与subtitleGlyph同一槽位的前导标记,画 11px 的accentColor图标。用于缩写文本表达不清的列类型(如日期时间族的时钟轮廓)。同时给出两者时图标优先、文本字形被忽略;两行的判定(表头加高、hasSubtitle)已把subtitleIcon计入。 -
修复
DataGridView(lists) 数据行缺横向分隔线、最后一行没有下边框:此前每行的Container只画背景色,竖线来自单元格的right边框,但整表唯一的横线只有表头下边框与最外层Border.all;当行数不满可视区(末行下方是空白)时末行像是悬空、没有收口线。现给_DataGridRow的行容器改用BoxDecoration,保留原背景色的同时补上bottom边框(颜色gridLineColor、宽度borderWidth,与竖线一致),使每行都有下边线、最后一行自然收口,符合 WinForms DataGridView 的行网格语义。 -
修复
ComboBox(common)下拉点击热区塌成文字大小:必须精确点到候选项/触发框的文字才能选中或展开,点行内空白或左右内边距无响应。根因是带alignment的Container内部走Align、其命中测试为deferToChild,背景虽铺满整行但空白区不参与命中;外层Listener默认同为deferToChild,于是整行热区缩到子节点尺寸。现给只读触发框、只读候选项与可编辑候选项(_EditableOption)三处Listener补上behavior: HitTestBehavior.opaque,使整行(含内边距与 Expanded 空白区)均可按下选中,零延迟交互与视觉保持不变。 -
新增
MarqueeSelector(lists):桌面风格的框选(rubber-band / marquee)行为层。在child区域内按住左键拖动、位移超过threshold(默认 4px,低于它视为普通点击)后进入框选,期间以onMarqueeUpdate(Rect)回调视口局部选框并绘制 accent 半透明填充 + 1px 描边浮层,起手触发onMarqueeStart、松手 / 取消触发onMarqueeEnd;enabled可整体关闭,canStart让宿主排除不该起手的地方(如内容区右缘滚动条命中带)。它不解释命中:把矩形换算成选中项交给宿主——定行高的网格 / 列表由宿主自己按几何算(配合ScrollController.offset),无需测量渲染对象。指针事件走Listener而非手势竞技场:祖先Listener在 pointer down 时缓存命中路径,整段拖动都收得到 move/up,既不与子项自己的onPointerDown选中抢竞技场,也不会给子项单击引入约 300ms 的双击判定延迟(本项目「零视觉延迟」约束)。零动画、无 Material 水波纹,取色链tokens ?? TokenScope.maybeOf(context) ?? DesktopTokens.winForm。 -
ComboBox新增iconBuilder(common):为候选项绘制前置图标(WinForms owner-draw 下拉的对应能力,如下拉项名前画一个引擎 / 实体图标)。同一个回调同时作用于收起态的当前值与展开态的每一行,图标盒子边长由controlHeight - 8推导并夹在 12~18px,与文本之间留compactSpacing;返回null表示该项不画图,缺省不传则完全保持既有纯文本外观。只读与可编辑两种模式都已接入(可编辑模式下图标置于文本框左侧、吃掉一份controlPaddingX以与只读模式对齐),零动画、无 Material 水波纹。 -
新增
ListPickerDialog(dialogs):泛型多选候选对话框——勾选任意个候选项后确定,show按候选原顺序回传选中项(取消 / 关闭回传null),自身不写回任何模型。由 daro 表设计器的StringPickerDialog(选择继承的父表)上收泛化而来,满足「无业务依赖 + Token 驱动 + 可独立复用」的入库条件。由DialogBox+CheckedListBox+Button组合,零动画、无 Material 水波纹;okText/cancelText缺省OK/Cancel(与MessageBox一致,中文由宿主传入);itemToString自定义行标签而回传的仍是原对象;emptyHint用于无候选时的引导(宿主可同时保留手输入口)。取色链tokens ?? TokenScope.maybeOf ?? DesktopTokens.winForm,与其它浮层一样默认走根导航器,故TokenScope需位于Navigator之上才跟随主题。泛型陷阱:selected的默认值const []在泛型声明处拿不到T,运行时实际是List<Never>,直接toSet()会让首次勾选的addAll抛Iterable<Never>类型错误——内部已改为Set<T>.from(...)。回归测试见test/list_picker_dialog_test.dart(按候选顺序回传、预勾选可取消、取消回传 null、空候选提示、T=int且不传selected的组合)。示例画廊 Dialogs 分类新增ListPickerDialog页,并计入example/test/smoke_test.dart。 -
Popover新增scrollable/maxHeight:内容过高时在面板内部滚动,而不是把整列铺出屏幕。修复前连接选择器这类下拉(db_lite 查询页「选择连接」有几十个连接)会把全部条目一次性渲染出来——面板高过视口顶部/底部被裁掉,且后面的条目根本选不到。scrollable: true时滚动视图位于带边框的面板内部(背景与边框固定不动,只有行在动),maxHeight缺省表示「最多占满视口、绝不超出」,显式给值则按值封顶(仍会与视口取小)。列表用ListItem、crossAxisAlignment: stretch的Column直接放即可,滚动条沿用控件库 token 化ScrollBar;零动画、无 Material 水波纹。回归测试见test/modern_components_test.dart(「Popover 内容过高时在面板内滚动」+ 未开启时的无界行为各一条),示例页新增 Scrollable 分组。 -
AnchoredOverlay新增maxHeight(Popover的底层实现):在布局之前用MediaQuery把上限与视口高度取小(double.infinity= 只受视口约束),并把ConstrainedBox套在被_contentKey测量的那层Container上——这样_remeasure量到的就是封顶后的尺寸,贴边夹取与OverlaySide.auto选边都能基于真实高度正确计算。null(默认)保持既有「无界、可溢出视口」行为,既有调用外观不变。 -
修复
AnchoredOverlay测量帧的无限宽崩溃:浮层内容在算出位置前挂在Offstage(offstage: true)下,而RenderOffstage对隐藏子节点用的是空约束(maxWidth = ∞)。任何依赖有界宽度的内容——DropDownButton的Column(crossAxisAlignment: stretch)、ListView等——在这一帧直接抛BoxConstraints forces an infinite width,调试模式下弹层根本打不开。现给被测量的那层套ConstrainedBox(maxWidth: 视口宽 - 2×8)(视口宽取自MediaQuery,取不到则不设限),使测量帧与定位后的约束一致。修复DropDownButton两条既有测试(opens menu / closes after selecting an item)与宿主「导出向导」底部三个下拉。 -
修复
DataGridView在rowCount == 0(仅表头)时的越界行号:拖拽多选经Listener命中空白数据区时,_rowAtY原会返回rowCount - 1(即-1),使宿主收到(-1, col)这类不存在的单元格。现在rowCount <= 0时直接返回null,空白区不再产生任何选中回调。宿主可放心用「rowCount: 0+ 只有表头」表示空结果集(如 db_lite 查询页 0 行结果、表数据页空表)。 -
Empty(overlay) 新增maxWidth参数:把内容列限制在给定宽度内,长文本(例如数据库返回的错误原文)在该宽度内换行并保持居中,action按钮紧随其下。此前宿主若用「Row(mainAxisSize.min)+Flexible(Text)+ 按钮」手绘居中提示,Flexible会把整行撑到容器全宽——文字被挤成一行省略号、按钮贴到容器最右缘甚至被裁掉。默认null不限制,既有调用行为不变。 -
修复
TabControl页面面板拿到无界高度导致整帧布局中断:自 Flutter 3.47 起,竖向Column的非 flex 子项不再被夹到剩余空间,而是拿到maxHeight = infinity(旧版本在有界时夹逼到剩余高度)。标签页内容只要要求显式高度就必然在performLayout断言——例如放 re_editor 代码编辑器的页签会抛CodeLineNumber should have an explicit height;断言中断布局后渲染树半残,之后每次鼠标移动都命中未布局的盒子,MouseTracker的_debugDuringDeviceUpdate因异常跳出而永久置位 → 控制台无限刷屏!_debugDuringDeviceUpdate+RenderBox was not laid out,界面表现为彻底卡死。现将页面面板包进Flexible(fit: FlexFit.loose):控件自身高度有界时面板填满剩余高度(即 WinFormsDisplayRectangle语义,与 3.47 之前的观感一致,页面底色/边框不再塌陷),置于DialogBox的IntrinsicHeight、滚动容器等无界场景时仍按内容自适应且不触发 flex 断言。回归测试见test/tab_control_body_test.dart。 -
DataGridView表头新增拖拽排序:onHeaderSort(按住列头标题横向拖动、松手即按该列排序,向右=升序、向左=降序)、sortColumn/sortAscending(在当前排序列标题右侧渲染 accent 色 ▲/▼ 箭头)。判定用「按下点 → 松开点」的横向总距离,不与起手阈值叠加,不足 8px 视为按住抖动不触发。拖动过程中箭头实时预示松手后将应用的方向;标题区光标为click、列头右缘内侧 8px 为resizeColumn(沿用columnWidths/onColumnResize改列宽),两者互不干扰。零动画、无 Material 水波纹。 -
DataGridView表头两种拖拽(拖标题排序 / 拖边框改列宽)改由Listener直接跟指针结算,不再依赖GestureDetector的拖拽回调。原因:真机上「按住列头左右拖」没有任何反应,而同样的操作在 widget 测试里(斜拖、起手先纵向抖一下、拖出整个网格、按下停顿 300ms、1px 慢拖 60 步)全部能结算——差异只可能出在手势竞技场的归属上。Listener的命中路径在 pointer down 时缓存,整段拖动都收得到事件,与谁赢竞技场无关。每个拖拽区仍保留一层只注册空onHorizontalDragStart的GestureDetector,唯一作用是占住竞技场,使拖列头不会连带外层横向SingleChildScrollView一起滚。顺带把改列宽从「逐帧delta.dx累加」换成「按下时列宽 + 按下点起算的总位移」,事件被合并 / 丢弃时宽度不再漂移;预示箭头改为位移达到阈值时才出现,且仅在预示状态真的变化时setState。 -
修复
DataGridView列宽拖拽命中区过小:resize 手柄原先用Positioned(right: -3)+ 6px 让手柄探出列头单元格右缘,但RenderBox.hitTest要求触点先落在父盒子尺寸内,探出的半边永远点不到——实测只有紧贴边框内侧约 2px 能拖动。现改为贴右缘内侧right: 0+ 8px,整条命中区都可点。 -
修复
ToolStrip在窄面板 / trailing 展开时RenderFlex overflowed ... on the right(如 db_lite 对象面板把中间栏拖窄,工具栏按钮 + 右侧ExpandableSearch总宽超出容器):左侧按钮组原与右锚trailing同处一个不换行Row,靠Spacer撑开,空间不足即溢出被裁。现将左侧按钮组放进Flexible(child: 横向 SingleChildScrollView)——trailing仍保持自然宽度钉在右缘、按钮组撑满剩余空间(视觉上与旧的Spacer完全一致),空间不够时按钮组横向滚动而非溢出;滚动区用ScrollConfiguration(...copyWith(scrollbars: false))隐藏桌面滚动条,外观不变。 -
新增
Splitter(containers):独立的可拖动分隔条(WinFormSplitter对应物)。与自带比例状态、只管两栏的SplitContainer不同,它只上报沿分割轴的像素增量(onDrag)配合onDragStart/onDragEnd,由宿主决定改哪一栏、改多少,因此可直接用于三栏外壳、停靠面板等宽度由外部状态掌控的布局。默认 5px 宽的命中区内居中画 1px 发丝线,静止用borderColor、hover / 拖动时用primaryColor,光标随方向为resizeLeftRight/resizeUpDown;零动画、无 Material 水波纹,取色链tokens ?? TokenScope.maybeOf(context) ?? DesktopTokens.winForm。 -
Splitter新增两个正交的外观开关(默认true,既有调用外观不变):showHairline管静止态是否画 1px 发丝线,false供「面板贴合」布局使用——分隔条不再插进Row/Column里占掉 5px 布局宽度,而是由宿主以浮层(Positioned)压在两栏拼缝上且不画线,拼缝既不会被看成间隙,也不会让中间面板两侧多出一条像边框的线;showHoverHighlight管悬浮 / 拖动时是否换成primaryColor高亮,false时发丝线保持静止色(showHairline: true)或任何状态都不着色(showHairline: false),并且不注册鼠标进出回调 → 悬停零重建。手柄始终保留resizeLeftRight/resizeUpDown光标与完整命中区,照样能拖。回归测试见test/splitter_test.dart(四种组合各一条)。 -
新增
StepBar(misc):向导式横向步骤条(编号圆标 + 步骤标题 + 连接短线),三态渲染(已完成=描边、当前=accent 实心、未到达=灰化),供导入 / 导出向导一类多页对话框标示当前进度;纯展示组件,翻页仍由宿主对话框按钮控制。零动画、无 Material 水波纹,取色链tokens ?? TokenScope.maybeOf(context) ?? DesktopTokens.winForm。 -
ProgressBar新增barColor(misc):覆盖进度条前景色。用于长任务对话框需要按结果着色的场景(如导出向导完成时整条转成功绿、失败转红),缺省null时仍取DesktopTokens.primaryColor,既有调用外观不变。色值由宿主作为构造参数传入,控件本身仍不硬编码任何颜色,marquee 模式同样生效。 -
新增
PageNavigator(data):输入跳页型分页器——首页 / 上一页 / 页码输入框 / 下一页 / 尾页 + 可选「共 N 页」标签,仅一个输入框输入页码回车跳转,无页码按钮阵列;输入框自动过滤非数字字符,非法输入回弹当前页。页码输入框的垂直 padding 沿用Input默认居中算法((controlHeight - fontSize)/2),避免isDense下textAlignVertical失效导致文字贴顶。pageCount可为null(总页数未知,按需 COUNT 模式):「共 N 页」显示为「共 ? 页」,下一页/尾页保持可点,尾页按钮改触发onGoLast回调(由调用方执行 COUNT 后跳转)。与页码阵列型Pagination并存。 -
Input新增textAlign参数:文本对齐方式透传给文本域(如页码输入框居中显示),默认TextAlign.start保持原行为。 -
移除重复组件
Item(common)与ListBox(lists):两者分别是ListItem/WinListView的功能子集,一并删除。Item→ListItem:DropDownButton.items公共类型改为List<ListItem>(选中仍按下即触发,菜单关合逻辑不变);Item的text参数对应ListItem.title,示例页 / quick_overview / 测试同步迁移;键盘激活回归测试改直接测Surface。ListBox→WinListView:list 模式参数完全一致,WinListView额外提供 details/icon 模式、builder 模式、onItemActivated双击激活与零延迟选中;删除list_box_page.dart示例页及其 main.dart / smoke_test 注册与三语 l10n 键;CheckedListBox文档不再引用ListBox。
-
修复
FieldRow在 debug 下崩溃 / 示例页空白:Row对非 flex 子项(非 stretch 对齐)不约束最大宽度,直接放Input(TextField) 会触发 "InputDecorator cannot have an unbounded width" 断言。FieldRow现将 child 包进松约束Flexible,子项获得有界最大宽度且不被强制拉伸——固定宽度写法(如SizedBox(width: 280, child: Input(...)))保持原布局。 -
修复
InlineEditor进入编辑时全选文本:桌面平台(Win/Linux/macOS)TextField.selectAllOnFocus默认 true,聚焦即全选,预设 collapsed 选区挡不住;Input新增selectAllOnFocus参数透传(默认 null 跟随平台),InlineEditor显式传false并保留 controller 预设末尾光标,首次单击进入编辑时光标直接置于内容末尾,再次点击编辑器内文本可将光标定位到点击位置。 -
TabControl可关闭标签(TabItem.onClose)的关闭按钮固定到标签最右缘:悬停时出现在右缘(不再跟在文字后面),图标+文字改为左对齐,Expanded文字吸收宽度变化,按钮出现/消失时文字位置不跳动;非可关闭标签保持原有居中布局。 -
Input新增obscureToggle参数:配合obscureText时在输入框右缘渲染自绘眼睛按钮,点击在掩码点与明文之间切换(密码可见性);hover / pressed 由hoverOverlayColor/pressedOverlayColor基于控件底色派生(明暗自适应),无 Material 水波纹与点击动画,点击不抢占输入框焦点;外部关闭obscureText时自动重置切换状态。 -
TabControl重绘为经典 WinForms 样式:控件色(control)标签条 + 底部发丝线;选中标签用 surface 底色、比未选中高 2px 且下探 1px 压住发丝线,与下方带边框的页面面板无缝连成一体(面板不画顶边,顶边由标签条底线 + 选中标签覆盖);未选中标签融入条底色,hover 由条底色派生(明暗自适应)。标签外形改自绘_TabChrome(圆角顶 + 三边描边),文本恢复常规字重,移除 accent 下划线。移除showUnderline参数(WinForms 无下划线语义);纯标签条场景(所有TabItem.child为 null)不再渲染页面面板与底线,仅保留标签条。 -
修复
ComboBox嵌入DialogBox时崩溃:内部LayoutBuilder与DialogBox的IntrinsicHeight冲突("LayoutBuilder does not support returning intrinsic dimensions",如 db_lite 新建连接 SQL Server 表单)。改为GlobalKey按需测量实际渲染宽度(下拉面板只在布局完成后才会打开,测量安全),顺带修复无界宽度约束下弹层宽度变为无穷大的隐患。 -
新增
ToolbarButton(menus):独立可用的工具栏按钮(图标 + 文本 / 仅图标),自绘 hover / pressed / 禁用态,支持iconColor功能强调色、showCaret下拉箭头、outlined边框触发器样式、textMaxWidth窄条省略,无 Material 水波纹与点击动画。区别于数据模型ToolStripButton,可挂在任意布局中。 -
IconBtn重写为自绘实现(不再委托Button):新增child(任意内容,如CustomPaint图标)、selected/selectedColor(accent 淡底选中态)、outline(边框)、size(固定命中区)参数,保留原 API 兼容;含 Focus + Enter/Space 键盘激活。 -
新增
ListItem(lists):高密度列表行(前置图标 + 标题 + 尾随),selectedColor支持浅底选中(文字保持前景色,树形场景),选中由Listener.onPointerDown零延迟触发,双击单独挂GestureDetector。 -
新增
SelectableCard(common):可选卡片(内容 + 选中淡底 + 右上对勾圆标),禁用时整体降透明并显示disabledLabel角标,PointerDown选中 + 双击动作。 -
新增
ExpandableSearch(form):可展开搜索框(收起为放大镜按钮 → 展开输入框),失焦且内容为空自动收起。 -
新增
InlineEditor(form):单元格内联编辑器(自动聚焦,Enter / 失焦提交,Esc 取消,防双触发);新增onChanged回调,每次文本变化时触发(可用于实时标记 dirty)。 -
TabControl增强:TabItem新增onClose(悬浮显示关闭按钮)/width(固定宽度)/contextMenuItems(逐标签右键菜单);TabControl新增tabBarColor/selectedTabColor/hoverTabColor/showUnderline(可关) /barHeight/tabWidth/scrollStep,标签溢出时两侧滚动箭头,选中下划线去掉AnimatedContainer动画。 -
DataGridView增强:新增showRowNumbers/rowNumberWidth/rowNumberBuilder(行号列,按下选中整行)、selectedCell/onCellSelected/onCellTap/onCellDoubleTap/onCellContext(单元格选中 / 单击 / 双击 / 右键,选中与单击由Listener.onPointerDown零延迟触发)、headerColor/gridLineColor/selectedTextColor/cellPaddingX/headerFontSize/rowHoverColor(行 hover 自持,避免整页重建)。 -
ListItem新增borderRadius参数(默认cornerRadius圆角,可传BorderRadius.zero用于高密度直角列表 / 对象面板)。 -
TabControl新增contentPadding参数(可关掉默认 8px 内容内边距,适配纯标签条场景,如 db_lite 对象视图标签栏)。 -
SelectableCard覆盖层(选中淡底 / 对勾圆标 / 禁用角标)由Stack改为CustomPaint自绘:Stack 在无界约束下无法布局(如DialogBox的IntrinsicHeight尺寸计算会崩溃),自绘让组件在任意约束下正常渲染,且不引入额外渲染层级。 -
Textarea新增expands(填满可用空间,用于代码编辑器)、style(覆盖文本样式,如 monospace 字体)与showBorder(关闭边框,供嵌入面板的编辑器使用)参数;expands: true时自动置空minLines/maxLines并透传TextField.expands。 -
ComboBox可编辑(editable)模式下拉面板移除Material(elevation)阴影与InkWell水波纹:改为纯Container边框面板 +Listener.onPointerDown按下即选中 +MouseRegionhover 高亮(与只读模式下拉一致),消除阴影 shader 编译与墨水动画开销。 -
新增
DialogBox:通用对话框外壳(标题栏+正文+可选 footer),承载自定义内容的模态窗口;标题栏用surfaceColor底色 +IconBtn关闭按钮,正文用窗口底色,扁平 WinForm 风格(无外边框、无 Material 阴影),自带DefaultTextStyle干净基线。命名避开 Flutter Material 的同名Dialog冲突。配合showDialog使用,模态行为(遮罩/Esc/返回值)仍由调用方掌控。 -
ToolStripButton/ToolStripDropDownButton新增可选iconColor参数,支持为工具条按钮图标指定语义强调色(如新建=绿、删除=红),默认仍使用DesktopTokens.foregroundColor。 -
ToolStrip下拉面板移除Material(elevation)与冗余双重边框,改为纯Container扁平 WinForm 风格,避免首次展开阴影 shader 编译延迟。 -
ToolStripDropDownButton支持分离式(split)按钮:新增可选onPressed,赋值时按钮主体(图标+文字)点击触发onPressed,右侧独立箭头点击才打开下拉菜单,主体与箭头之间用细分隔线隔开;不赋值时行为与旧版一致(整钮打开下拉)。 -
ToolStripButton/ToolStripDropDownButton按钮体优化:内容容器由「仅水平compactSpacing且无固定高度」改为撑满controlHeight高度(垂直居中)并水平方向给到compactSpacing * 2内边距,hover/按下高亮带不再贴着文字、图标文字不再紧贴,整条观感更舒展。split 模式的下拉箭头容器同步撑满controlHeight。 -
修复
ToolStrip下拉菜单项文本继承应用级DefaultTextStyle的decoration: double/yellow+fontWeight: bold样式(去掉Material兜底后触发):_ToolStripDropDownEntryWidget的文本显式声明decoration: TextDecoration.none+fontWeight: FontWeight.w400,消除菜单项黄色双下划线与加粗。 -
优化
ToolStripDropDownButton分离式(split)按钮的渲染:原先主体与下拉箭头是两颗独立 pill(各自 hover 背景 + 圆角),悬浮时整体观感"变宽"且中间分割线被同色 hover 底色淹没而不可见。现改为整颗做成"统一的一颗按钮"——悬浮时整体一个 hover 背景,主体与箭头之间用一条常驻 1px 占位(非悬浮时为透明)、仅悬浮时才着色的细分隔线隔开,既消除悬浮变宽、又让分割线在统一底色上清晰可见。 -
修复 split 按钮分割线在明亮主题下不可见:分割线颜色由固定
borderColor(亮色下与 hover 底色几乎同色)改为基于 hover 底色Color.alphaBlend的明暗自适应(暗底提亮叠白、亮底加深叠黑),符合项目"hover/选中色必须明暗自适应"规范,两套主题下均可见。 -
CheckRow新增trailing参数:行尾可渲染任意 widget(如状态标注),便于在选项列表中标示不可用/未实现的条目。 -
ContextMenuStrip新增静态入口showContextMenu(context, items, position):无需包裹子树,可在右键时刻动态构建菜单内容后直接弹出(如表格单元格右键菜单,命中哪格决定了菜单作用于哪格)。同时菜单弹出位置增加屏幕边界夹取,右键在屏幕右/下缘时面板自动收回屏幕内,不再溢出不可见。 -
ComboBox只读模式下拉重写:原实现基于 FlutterDropdownButton,弹出带 Material 淡入/滑动动画,不符合传统桌面习惯。现改为自绘 WinForm 风格即时展开下拉列表:Listener.onPointerDown触发、OverlayEntry+CompositedTransformFollower定位、无动画即时显示、hover 高亮、选中项主色填充、点击外部或选项后即时关闭。 -
ToolStrip增强:新增trailing(右侧任意 widget,如Pagination)与trailingItems(右侧条目)支持左右分区布局;新增borderOnTop(分隔线画在顶部,适配底部停靠)与openUpward(下拉面板向上弹出,适配底部工具栏,并夹取面板位置避免溢出屏幕右缘)。ToolStripDropDownButton.text改为可选,支持纯图标下拉按钮(隐藏下拉箭头)。 -
Pagination尺寸调整:页码/箭头按钮边长由controlHeight * 1.2改为controlHeight,可直接嵌入ToolStrip等紧凑容器不溢出。 -
ContextMenuStrip/MenuStrip关闭遮罩修复:遮罩原为GestureDetector(translucent, onTap, ColoredBox),但ColoredBox的渲染对象是 opaque 命中,遮罩子树命中测试返回 true 后 Stack 即停止向下探测——底部控件完全收不到事件,菜单打开时第一次点击只被用来关菜单(浪费一次点击,右键换菜单同样被吃掉)。现改为无子节点的半透明Listener+onPointerDown:命中测试返回 false(事件穿透到底部控件),但自身仍在命中列表中(按下瞬间即关菜单)——同一次点击既关菜单又落在下方控件上,与原生桌面行为一致。 -
ContextMenuStrip弹出位置修复:PointerEvent.position本身就是全局坐标,旧代码又对它做了一次box.localToGlobal()转换,把触发控件自身的窗口偏移重复叠加,导致菜单向右下偏移。现直接传入event.position,菜单精确出现在光标处。 -
ListView行选中延迟修复:onTap与onDoubleTap同注册会让单击被双击判定窗口 hold 约 300ms。选中改为Listener.onPointerDown(按下瞬间触发、零延迟),双击激活单独由GestureDetector.onDoubleTap处理。 -
MenuStrip显式关闭菜单项文字下划线并恢复常规字重:之前为优化首屏速度把下拉面板的Material替换为Container,但 Text 不再有 Material 的DefaultTextStyle兜底,会继承应用级某个带decoration: underline / TextDecorationStyle.double / color: yellow且fontWeight: bold的样式,导致下拉菜单项文字下方出现两条黄线、字体加粗。已在_MenuTopItem/_MenuDropDownItem的 Text 显式decoration: TextDecoration.none+fontWeight: FontWeight.w400覆盖。 -
MenuStrip顶层菜单项高亮修复:行内crossAxisAlignment改为stretch,hover/打开态背景填满整行高度(此前只包住文字形成一条窄横带,视觉上像菜单项上的"横线")。 -
MenuStrip下拉面板性能优化:弃用Material(elevation)(阴影首次计算 / shader 编译是"首次展开慢、之后快"的主因)与冗余的CompositedTransformTarget,改纯Container(扁平 WinForm 风格),首次展开更跟手。 -
新增
FieldRow:横向表单行(左 label 右对齐固定宽 + 右侧控件),经典桌面(WinForms)表单布局;label缺省时渲染同宽占位保持对齐。 -
新增
IconBtn:轻量无边框图标按钮(工具栏/标题栏),悬停 ghost 高亮,可选 tooltip。命名避开 Flutter Material 的同名IconButton冲突。 -
Input新增obscureText参数,支持密码框。 -
CheckBox重写:弃用 FlutterCheckbox(自带勾选动画、无法关闭),改为自绘方框 + 勾号,勾选状态瞬间切换、无动画(对齐 WinForms 快节奏手感)。API 不变,保留 label 点击切换、Focus/键盘(Enter/Space)切换与 disabled 视觉。 -
Button重写聚焦行为:弃用TextButton(其InkWell.canRequestFocus会在按下瞬间请求焦点,导致长按/按住移走鼠标也显示焦点边框),改为GestureDetector + MouseRegion + Focus手绘实现——按下只显示 pressed 视觉,完整点击(松开)才requestFocus()显示焦点边框,长按移走(tap 取消)不聚焦;Tab 导航聚焦正常,焦点在按钮上按 Enter/Space 可激活。视觉逻辑(hover/pressed/disabled/ghost)与 token 取色全部保留。 -
DesktopTokens默认(WinForm)控件密度调整:controlHeight24→28、fontSize12→13、controlPaddingX8→12,使按钮/输入框/复选框等统一变大,更贴合桌面应用的舒适点击尺寸。 -
MenuStrip悬停行为修正:bar 级Listener现在仅在已有菜单打开时才随悬停切换顶层菜单(_onBarHover在_openIndex == -1时直接返回)。即 WinForm 经典行为——必须先点击打开菜单,之后悬停才切换;未打开任何菜单时,单纯悬停不会自动展开。单项的MouseRegion仅保留悬停高亮,点击仍由GestureDetector.onTap开关。 -
MenuStrip悬停展开改为 bar 级Listener驱动:原先依赖每个顶层项的MouseRegion.onEnter来悬停打开/切换,但该回调在"尚未打开过任何菜单"的首次悬停时可能不触发(默认deferToChild命中问题),表现为悬停不展开。现改为在菜单栏包裹一层Listener(behavior: HitTestBehavior.opaque, onPointerHover),按指针全局 x 坐标命中对应顶层项并打开,首次悬停与已展开后切换都稳定生效;单项的MouseRegion仅保留悬停高亮。 -
MenuStrip修复:下拉遮罩(_MenuDropDown的 dismiss scrim)原本为全屏Positioned.fill, 会拦截覆盖在菜单栏顶部区域的指针事件,导致"菜单展开后悬停其它顶层菜单不会自动切换"的行为失效。 现改为从菜单栏底边(position.dy)开始向下覆盖,顶部菜单栏区域保持裸露, 悬停切换恢复正常工作(点击空白处关闭的行为不受影响)。 -
Button增强:新增 [ButtonVariant](solid默认 /ghost无边框),并将内容参数化—— 新增child(Widget?)以支持任意内容(如图标 + 文字列),text变为可选语义标签。ghost变体使用透明背景,悬停 / 按下态以hoverOverlayColor/pressedOverlayColor混合controlColor,适合工具栏 / ribbon 的无边框按钮组。
- 以 shadcn/ui 组件清单为参考,原生补充 43 个缺失组件(不做 shadcn 风格化集合,
沿用 headless +
DesktopTokens架构;命名用 WinForm 语义名 / 裸名)。 - 新增
DesktopTokens.shadcn现代预设,并扩展语义色 token:muted/secondary/accent/destructive/card/popover/ring/barrier、圆角刻度、 阴影与图表色板(TokenColor扩展提供 hover/pressed/disabled 派生色)。 - 新增浮层基础设施:
OverlayController、AnchoredOverlay、ModalOverlay、FocusTrap(锚定定位 / 模态遮罩 / 焦点圈闭),以及Surface交互表面基元。 - 新增通用补充组件:
TypeStyle、Kbd、Separator、Tag、Field、Item、Marker、ButtonGroup、InputGroup、Textarea、Toggle、ToggleGroup、ToggleSwitch、InputOtp。 - 新增容器组件:
GroupBox(Card)、TabControl(Tabs)、SplitContainer(Resizable)、Accordion、Collapsible、Sheet、SidePanel(Drawer)、Sidebar、Carousel。 - 新增浮层组件:
Popover、HoverCard、DropDownButton(DropdownMenu)、MessageBox(Dialog / AlertDialog,含MessageBox.show与 WinForm 按钮组合)、Command、Toast/ToastHost、Direction、Empty。 - 新增数据与杂项组件:
Chart(柱/折线/环图,无第三方依赖)、Pagination、Alert、Attachment、Avatar、Breadcrumb、Bubble、Message、MessageScroller、Questionnaire、Skeleton、Spinner。 - 组件画廊新增 Supplements / Containers / Overlay 分类与 43 个演示页。
- 更新 components.md 第八节(shadcn 参考映射:新增 43 / 已覆盖 21)。
- Initial scaffold:
DesktopTokenswith a WinForm-style default preset. - Added
TokenScopefor app-level token theming. - Added WinForm-style
Button,Input, andLabelwidgets. - Added
CheckBox— WinForm-style check box with label support. - Added
RadioButton<T>— WinForm-style radio button with mutual exclusion group. - Added
ComboBox<T>— WinForm-style drop-down combo box (editable / read-only). - Added
ListBox<T>— WinForm-style list box with single / multi-select. - Added
WinListView<T>— WinForm-style list view with Details / icon / multi-select modes. - Added
TreeView<T>— WinForm-style tree view with expand / collapse / select. - Added
NumericUpDown— WinForm-style numeric up/down control. - Added
DateTimePicker— WinForm-style date / time picker. - Added
ProgressBar— WinForm-style progress bar (determinate / marquee). - Added
MenuStrip— WinForm-style main menu bar with drop-down sub-menus. - Added
ContextMenuStrip— WinForm-style right-click context menu (reusesMenuModel). - Added
ToolStrip— WinForm-style toolbar (buttons / separators / labels / drop-downs). - Added
StatusStrip— WinForm-style status bar with panels. - Added
Control— headless control base class (focus / disabled / semantics contract). - Added
ControlSemantics— accessibility wrapper for custom controls. - Added
DataGridView— WinForm-style data grid with virtual scrolling &CellDirtyTracker. - Added
ScrollBar/StandaloneScrollBar— WinForm-style scroll bars (H/V). - Added
TrackBar— WinForm-style track bar / slider. - Added
ScrollableControl— headless scrollable container. - Added
LinkLabel— WinForm-style hyperlink label. - Added
MaskedTextBox— WinForm-style masked text input. - Added
RichTextBox— WinForm-style multi-line text editor. - Added
MonthCalendar— WinForm-style month calendar. - Added
CheckedListBox<T>— WinForm-style checked list box. - Added
DomainUpDown<T>— WinForm-style domain up/down. - Added
PropertyGrid— WinForm-style property grid with categories. - Added
ColorDialog— WinForm-style colour picker dialog. - Added
BindingNavigator— WinForm-style data binding navigator. - Added
WinToolTip— WinForm-style tool tip. - Added
ErrorProvider— WinForm-style form validation indicator. - Added
RovingTabindex— declarative keyboard focus state machine. - Added
ResponsiveTokenScope— media-query-aware token switching.