@ds-mo/ui 14.20.0 → 14.21.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.
Files changed (257) hide show
  1. package/dist/.package-ready.json +1 -1
  2. package/dist/agent-patterns.json +1 -1
  3. package/dist/agent.json +386 -33
  4. package/dist/angular/ds-chip.d.ts +1 -1
  5. package/dist/angular/ds-chip.js +3 -3
  6. package/dist/angular/ds-filter-menu.d.ts +7 -1
  7. package/dist/angular/ds-filter-menu.js +7 -4
  8. package/dist/angular/ds-input.d.ts +1 -1
  9. package/dist/angular/ds-input.js +3 -3
  10. package/dist/angular/ds-tab-group.d.ts +1 -1
  11. package/dist/angular/ds-tab-group.js +3 -3
  12. package/dist/angular/ds-table-filter.d.ts +7 -1
  13. package/dist/angular/ds-table-filter.js +7 -4
  14. package/dist/angular/ds-table-group.d.ts +29 -0
  15. package/dist/angular/ds-table-group.js +48 -0
  16. package/dist/angular/ds-table-search.d.ts +20 -0
  17. package/dist/angular/ds-table-search.js +49 -0
  18. package/dist/angular/ds-table.d.ts +1 -1
  19. package/dist/angular/ds-table.js +3 -3
  20. package/dist/angular/index.d.ts +1 -1
  21. package/dist/angular/index.js +2 -0
  22. package/dist/angular/proxies.d.ts +2 -0
  23. package/dist/angular/proxies.js +2 -0
  24. package/dist/components/ds-agent-activity.js +1 -1
  25. package/dist/components/ds-agent-questionnaire.js +1 -1
  26. package/dist/components/ds-agent-response.js +1 -1
  27. package/dist/components/ds-agent-source-list.js +1 -1
  28. package/dist/components/ds-agent-tool-call.js +1 -1
  29. package/dist/components/ds-attachment-list.js +1 -1
  30. package/dist/components/ds-badge.js +1 -1
  31. package/dist/components/ds-banner.js +1 -1
  32. package/dist/components/ds-bar-action.js +1 -1
  33. package/dist/components/ds-bar-nav.js +1 -1
  34. package/dist/components/ds-bar-title.js +1 -1
  35. package/dist/components/ds-bar-workflow.js +1 -1
  36. package/dist/components/ds-breadcrumb.js +1 -1
  37. package/dist/components/ds-button-filled.js +1 -1
  38. package/dist/components/ds-button-unfilled.js +1 -1
  39. package/dist/components/ds-card-chart.js +1 -1
  40. package/dist/components/ds-card-overview.js +1 -1
  41. package/dist/components/ds-card-setting.js +1 -1
  42. package/dist/components/ds-chart-legend.js +1 -1
  43. package/dist/components/ds-chart.js +1 -1
  44. package/dist/components/ds-checkbox.js +1 -1
  45. package/dist/components/ds-chip.js +1 -1
  46. package/dist/components/ds-chip.js.map +1 -1
  47. package/dist/components/ds-code-block.js +1 -1
  48. package/dist/components/ds-conversation-list-item.js +1 -1
  49. package/dist/components/ds-conversation-list-section.js +1 -1
  50. package/dist/components/ds-empty-state.js +1 -1
  51. package/dist/components/ds-field.js +1 -1
  52. package/dist/components/ds-filter-menu.js +1 -1
  53. package/dist/components/ds-input.js +1 -1
  54. package/dist/components/ds-markdown.js +1 -1
  55. package/dist/components/ds-menu.js +1 -1
  56. package/dist/components/ds-message-actions.js +1 -1
  57. package/dist/components/ds-message-composer.js +1 -1
  58. package/dist/components/ds-message-scroller.js +1 -1
  59. package/dist/components/ds-message-scroller.js.map +1 -1
  60. package/dist/components/ds-message.js +1 -1
  61. package/dist/components/ds-mobile-bar-nav.js +1 -1
  62. package/dist/components/ds-mobile-header.js +1 -1
  63. package/dist/components/ds-mobile-section-switcher.js +1 -1
  64. package/dist/components/ds-mobile-sheet-nav.js +1 -1
  65. package/dist/components/ds-modal.js +1 -1
  66. package/dist/components/ds-pagination.js +1 -1
  67. package/dist/components/ds-panel-nav.js +1 -1
  68. package/dist/components/ds-panel-sub-nav.js +1 -1
  69. package/dist/components/ds-panel-tool-header.js +1 -1
  70. package/dist/components/ds-panel-tool-search.js +1 -1
  71. package/dist/components/ds-panel-tool-search.js.map +1 -1
  72. package/dist/components/ds-panel-tools.js +1 -1
  73. package/dist/components/ds-paper-texture.js +1 -1
  74. package/dist/components/ds-radio.js +1 -1
  75. package/dist/components/ds-select.js +1 -1
  76. package/dist/components/ds-shell-app.js +1 -1
  77. package/dist/components/ds-shell-page.js +1 -1
  78. package/dist/components/ds-shell-tools.js +1 -1
  79. package/dist/components/ds-slider.js +1 -1
  80. package/dist/components/ds-swatch-picker.js +1 -1
  81. package/dist/components/ds-tab-group.js +1 -1
  82. package/dist/components/ds-table-filter.js +1 -1
  83. package/dist/components/ds-table-filter.js.map +1 -1
  84. package/dist/components/ds-table-group.d.ts +11 -0
  85. package/dist/components/ds-table-group.js +2 -0
  86. package/dist/components/ds-table-group.js.map +1 -0
  87. package/dist/components/ds-table-saved-views.js +1 -1
  88. package/dist/components/ds-table-search.d.ts +11 -0
  89. package/dist/components/ds-table-search.js +2 -0
  90. package/dist/components/ds-table-search.js.map +1 -0
  91. package/dist/components/ds-table-sort.js +1 -1
  92. package/dist/components/ds-table-sort.js.map +1 -1
  93. package/dist/components/ds-table-toolbar.js +1 -1
  94. package/dist/components/ds-table-toolbar.js.map +1 -1
  95. package/dist/components/ds-table.js +1 -1
  96. package/dist/components/ds-table.js.map +1 -1
  97. package/dist/components/ds-tag.js +1 -1
  98. package/dist/components/ds-text.js +1 -1
  99. package/dist/components/ds-toast.js +1 -1
  100. package/dist/components/ds-tooltip-chart.js +1 -1
  101. package/dist/components/ds-tooltip.js +1 -1
  102. package/dist/components/ds-typing-indicator.js +1 -1
  103. package/dist/components/{p-Bf7PZJPT.js → p-5Z4oYuiK.js} +2 -2
  104. package/dist/components/{p-DIlScMvI.js → p-6rB0eAda.js} +2 -2
  105. package/dist/components/{p-CptSB-tA.js → p-9ykZwPlI.js} +2 -2
  106. package/dist/components/{p-BHhmB9-4.js → p-B0kSlcaw.js} +2 -2
  107. package/dist/components/{p-DWjTOoXs.js → p-B1wMpt1z.js} +2 -2
  108. package/dist/components/p-BEttT0UB.js +2 -0
  109. package/dist/components/p-BEttT0UB.js.map +1 -0
  110. package/dist/components/p-BFit8o0r.js +2 -0
  111. package/dist/components/p-BFit8o0r.js.map +1 -0
  112. package/dist/components/{p-fRDzpfi9.js → p-BXv6RpoF.js} +2 -2
  113. package/dist/components/{p-D7QlTWbN.js → p-BbG7nOcz.js} +2 -2
  114. package/dist/components/{p-B2FT4Da6.js → p-Bc_z1UwJ.js} +2 -2
  115. package/dist/components/{p-Bx5BSd6F.js → p-BcxidW9k.js} +2 -2
  116. package/dist/components/{p-1UAVanY9.js → p-Bd8I2oXN.js} +2 -2
  117. package/dist/components/{p-DGe5oXR0.js → p-Bjq1KP_Y.js} +2 -2
  118. package/dist/components/p-Bjq1KP_Y.js.map +1 -0
  119. package/dist/components/{p-DW5Ita-P.js → p-BnTPuV3x.js} +2 -2
  120. package/dist/components/{p-DW5Ita-P.js.map → p-BnTPuV3x.js.map} +1 -1
  121. package/dist/components/p-BqVXMEJm.js +2 -0
  122. package/dist/components/p-BqVXMEJm.js.map +1 -0
  123. package/dist/components/{p-DdH7b4JF.js → p-CBymzuOO.js} +2 -2
  124. package/dist/components/{p-BjRD57w3.js → p-CE2b5GPu.js} +2 -2
  125. package/dist/components/{p-DfDoqOlx.js → p-CEnoPUn5.js} +2 -2
  126. package/dist/components/{p-DBYv7fRq.js → p-CFkZSDwI.js} +2 -2
  127. package/dist/components/{p-Bb4KnRy0.js → p-CTH3dSYg.js} +2 -2
  128. package/dist/components/{p-BmssRAEZ.js → p-CZ144LS5.js} +2 -2
  129. package/dist/components/{p-B-HsfQOK.js → p-Cd1JnnVK.js} +2 -2
  130. package/dist/components/p-CeKa4VbU.js +2 -0
  131. package/dist/components/{p-AtUP95E_.js.map → p-CeKa4VbU.js.map} +1 -1
  132. package/dist/components/{p-CDw_WEVt.js → p-Cnsvgx1M.js} +2 -2
  133. package/dist/components/{p-BYFS2qWb.js → p-CpeJMKJ5.js} +2 -2
  134. package/dist/components/{p-DM1Z_hh0.js → p-D36EmETH.js} +2 -2
  135. package/dist/components/{p-DFC0sRM-.js → p-DI8DUozc.js} +2 -2
  136. package/dist/components/{p-v4oqkJms.js → p-DSy1oOnd.js} +2 -2
  137. package/dist/components/{p-v4oqkJms.js.map → p-DSy1oOnd.js.map} +1 -1
  138. package/dist/components/{p-DQBT1Jkf.js → p-DbLLH3hr.js} +2 -2
  139. package/dist/components/{p-B6rSDhJY.js → p-Dit6JmAK.js} +2 -2
  140. package/dist/components/{p-caLOcQUK.js → p-DzPtYdXy.js} +2 -2
  141. package/dist/components/{p-Do8wbFff.js → p-XaCYqck3.js} +2 -2
  142. package/dist/components/{p-DKt_8s-U.js → p-Y5_MkCFn.js} +2 -2
  143. package/dist/components/{p-BUexfjjg.js → p-YDxDyedE.js} +2 -2
  144. package/dist/components/{p-L8IIeDXM.js → p-_C-XRpCB.js} +2 -2
  145. package/dist/components/{p-CyZqk196.js → p-bHnk8t5I.js} +2 -2
  146. package/dist/components/p-hYjmOPCI.js +2 -0
  147. package/dist/components/p-hYjmOPCI.js.map +1 -0
  148. package/dist/components/{p-ChfVRPHw.js → p-pUOA3iDG.js} +2 -2
  149. package/dist/components/{p-DLbHgbVj.js → p-pnO8tAYB.js} +2 -2
  150. package/dist/components/{p-CCmgtju-.js → p-pxN8JGEh.js} +2 -2
  151. package/dist/components/p-pxN8JGEh.js.map +1 -0
  152. package/dist/components/{p-B4wTnsUL.js → p-w9fkkwL2.js} +2 -2
  153. package/dist/components/p-x5u5Ueli.js +2 -0
  154. package/dist/components/{p-BeA6Jv-3.js.map → p-x5u5Ueli.js.map} +1 -1
  155. package/dist/docs/components.json +1291 -33
  156. package/dist/mcp-data/registry/button-filled.json +1 -0
  157. package/dist/mcp-data/registry/button-unfilled.json +1 -0
  158. package/dist/mcp-data/registry/chip.json +39 -2
  159. package/dist/mcp-data/registry/filter-menu.json +84 -11
  160. package/dist/mcp-data/registry/input.json +54 -2
  161. package/dist/mcp-data/registry/panel-tool-search.json +4 -5
  162. package/dist/mcp-data/registry/registry.json +391 -32
  163. package/dist/mcp-data/registry/select.json +1 -0
  164. package/dist/mcp-data/registry/tab-group.json +21 -2
  165. package/dist/mcp-data/registry/table-filter.json +79 -9
  166. package/dist/mcp-data/registry/table-group.json +301 -0
  167. package/dist/mcp-data/registry/table-search.json +343 -0
  168. package/dist/mcp-data/registry/table-sort.json +1 -1
  169. package/dist/mcp-data/registry/table-toolbar.json +7 -6
  170. package/dist/mcp-data/registry/table.json +55 -17
  171. package/dist/react/components.d.ts +2 -0
  172. package/dist/react/components.js +2 -0
  173. package/dist/react/ds-filter-menu.d.ts +2 -1
  174. package/dist/react/ds-filter-menu.js +1 -0
  175. package/dist/react/ds-table-filter.d.ts +2 -1
  176. package/dist/react/ds-table-filter.js +1 -0
  177. package/dist/react/ds-table-group.d.ts +14 -0
  178. package/dist/react/ds-table-group.js +16 -0
  179. package/dist/react/ds-table-search.d.ts +14 -0
  180. package/dist/react/ds-table-search.js +16 -0
  181. package/dist/styles/table.css +46 -0
  182. package/dist/types/components/Chip/Chip.d.ts +5 -0
  183. package/dist/types/components/FilterMenu/FilterMenu.d.ts +26 -0
  184. package/dist/types/components/Input/Input.d.ts +6 -0
  185. package/dist/types/components/TabGroup/TabGroup.d.ts +2 -0
  186. package/dist/types/components/Table/Table.d.ts +6 -0
  187. package/dist/types/components/Table/index.d.ts +1 -1
  188. package/dist/types/components/Table/table-cell-model.d.ts +11 -1
  189. package/dist/types/components/Table/table-highlight.d.ts +12 -0
  190. package/dist/types/components/Table/table-model.d.ts +6 -5
  191. package/dist/types/components/Table/table-render-model.d.ts +1 -1
  192. package/dist/types/components/Table/table-row-view.d.ts +4 -1
  193. package/dist/types/components/Table/table-types.d.ts +22 -4
  194. package/dist/types/components/Table/table-virtual-model.d.ts +2 -0
  195. package/dist/types/components/TableFilter/TableFilter.d.ts +9 -1
  196. package/dist/types/components/TableGroup/TableGroup.d.ts +60 -0
  197. package/dist/types/components/TableSearch/TableSearch.d.ts +56 -0
  198. package/dist/types/components/TableSearch/table-search-model.d.ts +10 -0
  199. package/dist/types/components/TableSearch/table-search-types.d.ts +10 -0
  200. package/dist/types/components.d.ts +386 -6
  201. package/dist/types/utils/choice-list-parts.d.ts +11 -1
  202. package/dist/types/utils/select-controller.d.ts +1 -1
  203. package/dist/vue/components.d.ts +2 -0
  204. package/dist/vue/components.js +2 -0
  205. package/dist/vue/ds-chip.js +2 -0
  206. package/dist/vue/ds-filter-menu.js +5 -0
  207. package/dist/vue/ds-input.js +3 -0
  208. package/dist/vue/ds-tab-group.js +1 -0
  209. package/dist/vue/ds-table-filter.js +5 -0
  210. package/dist/vue/ds-table-group.d.ts +3 -0
  211. package/dist/vue/ds-table-group.js +20 -0
  212. package/dist/vue/ds-table-search.d.ts +3 -0
  213. package/dist/vue/ds-table-search.js +22 -0
  214. package/dist/vue/ds-table.js +2 -0
  215. package/package.json +1 -1
  216. package/dist/components/p-AtUP95E_.js +0 -2
  217. package/dist/components/p-B5-R5mb8.js +0 -2
  218. package/dist/components/p-B5-R5mb8.js.map +0 -1
  219. package/dist/components/p-BeA6Jv-3.js +0 -2
  220. package/dist/components/p-BkelrY4-.js +0 -2
  221. package/dist/components/p-BkelrY4-.js.map +0 -1
  222. package/dist/components/p-CCmgtju-.js.map +0 -1
  223. package/dist/components/p-DA5H_Iq_.js +0 -2
  224. package/dist/components/p-DA5H_Iq_.js.map +0 -1
  225. package/dist/components/p-DGe5oXR0.js.map +0 -1
  226. /package/dist/components/{p-Bf7PZJPT.js.map → p-5Z4oYuiK.js.map} +0 -0
  227. /package/dist/components/{p-DIlScMvI.js.map → p-6rB0eAda.js.map} +0 -0
  228. /package/dist/components/{p-CptSB-tA.js.map → p-9ykZwPlI.js.map} +0 -0
  229. /package/dist/components/{p-BHhmB9-4.js.map → p-B0kSlcaw.js.map} +0 -0
  230. /package/dist/components/{p-DWjTOoXs.js.map → p-B1wMpt1z.js.map} +0 -0
  231. /package/dist/components/{p-fRDzpfi9.js.map → p-BXv6RpoF.js.map} +0 -0
  232. /package/dist/components/{p-D7QlTWbN.js.map → p-BbG7nOcz.js.map} +0 -0
  233. /package/dist/components/{p-B2FT4Da6.js.map → p-Bc_z1UwJ.js.map} +0 -0
  234. /package/dist/components/{p-Bx5BSd6F.js.map → p-BcxidW9k.js.map} +0 -0
  235. /package/dist/components/{p-1UAVanY9.js.map → p-Bd8I2oXN.js.map} +0 -0
  236. /package/dist/components/{p-DdH7b4JF.js.map → p-CBymzuOO.js.map} +0 -0
  237. /package/dist/components/{p-BjRD57w3.js.map → p-CE2b5GPu.js.map} +0 -0
  238. /package/dist/components/{p-DfDoqOlx.js.map → p-CEnoPUn5.js.map} +0 -0
  239. /package/dist/components/{p-DBYv7fRq.js.map → p-CFkZSDwI.js.map} +0 -0
  240. /package/dist/components/{p-Bb4KnRy0.js.map → p-CTH3dSYg.js.map} +0 -0
  241. /package/dist/components/{p-BmssRAEZ.js.map → p-CZ144LS5.js.map} +0 -0
  242. /package/dist/components/{p-B-HsfQOK.js.map → p-Cd1JnnVK.js.map} +0 -0
  243. /package/dist/components/{p-CDw_WEVt.js.map → p-Cnsvgx1M.js.map} +0 -0
  244. /package/dist/components/{p-BYFS2qWb.js.map → p-CpeJMKJ5.js.map} +0 -0
  245. /package/dist/components/{p-DM1Z_hh0.js.map → p-D36EmETH.js.map} +0 -0
  246. /package/dist/components/{p-DFC0sRM-.js.map → p-DI8DUozc.js.map} +0 -0
  247. /package/dist/components/{p-DQBT1Jkf.js.map → p-DbLLH3hr.js.map} +0 -0
  248. /package/dist/components/{p-B6rSDhJY.js.map → p-Dit6JmAK.js.map} +0 -0
  249. /package/dist/components/{p-caLOcQUK.js.map → p-DzPtYdXy.js.map} +0 -0
  250. /package/dist/components/{p-Do8wbFff.js.map → p-XaCYqck3.js.map} +0 -0
  251. /package/dist/components/{p-DKt_8s-U.js.map → p-Y5_MkCFn.js.map} +0 -0
  252. /package/dist/components/{p-BUexfjjg.js.map → p-YDxDyedE.js.map} +0 -0
  253. /package/dist/components/{p-L8IIeDXM.js.map → p-_C-XRpCB.js.map} +0 -0
  254. /package/dist/components/{p-CyZqk196.js.map → p-bHnk8t5I.js.map} +0 -0
  255. /package/dist/components/{p-ChfVRPHw.js.map → p-pUOA3iDG.js.map} +0 -0
  256. /package/dist/components/{p-DLbHgbVj.js.map → p-pnO8tAYB.js.map} +0 -0
  257. /package/dist/components/{p-B4wTnsUL.js.map → p-w9fkkwL2.js.map} +0 -0
package/dist/agent.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": "1.0.0",
3
3
  "package": "@ds-mo/ui",
4
- "packageVersion": "14.20.0",
4
+ "packageVersion": "14.21.0",
5
5
  "kind": "components",
6
6
  "entries": [
7
7
  {
@@ -1766,6 +1766,7 @@
1766
1766
  ],
1767
1767
  "states": [
1768
1768
  "Every size applies one complete control-density recipe across frame height, inline padding, icon zone, text-container inset, gap, and radius.",
1769
+ "Every button has a minimum inline size equal to its resolved height. Short labels therefore form a square control while longer labels continue to hug their content.",
1769
1770
  "Set isInset only when the button is nested inside a same-size control. The default single inset removes 4px overall; insetDepth double removes 8px overall so the parent can add 4px per edge while preserving its outer alignment box. Double inset falls back to single at xs to protect minimum icon geometry.",
1770
1771
  "Use only one filled action per local decision area; render all secondary actions with ButtonUnfilled.",
1771
1772
  "Choose brand or neutral for general commands. Reserve positive, negative, warning, and caution for matching action consequences, and AI, guide, or walkthrough for actions that enter those feature experiences.",
@@ -1980,6 +1981,7 @@
1980
1981
  ],
1981
1982
  "states": [
1982
1983
  "Every size applies one complete control-density recipe across frame height, inline padding, icon zone, text-container inset, gap, and radius.",
1984
+ "Every button has a minimum inline size equal to its resolved height. Short labels therefore form a square control while longer labels continue to hug their content.",
1983
1985
  "Set isInset only when the button is nested inside a same-size control. The default single inset removes 4px overall; insetDepth double removes 8px overall so the parent can add 4px per edge while preserving its outer alignment box. Double inset falls back to single at xs to protect minimum icon geometry.",
1984
1986
  "A true pressed toggle and owner-controlled isActive emphasis share the selected visual treatment, but only pressed supplies toggle semantics and dsChange.",
1985
1987
  "General content UI keeps the selected interaction fill and border for pressed or active emphasis.",
@@ -3049,6 +3051,7 @@
3049
3051
  "The dismiss action is the chip's only interaction, and the parent owns data mutation after dsRemove.",
3050
3052
  "Long labels remain on one line and truncate only when the consuming layout supplies a maximum width; otherwise the chip sizes to its content.",
3051
3053
  "Rounded shape is a visual choice and does not change semantics or interaction.",
3054
+ "isInset opts into reduced outer geometry only when Chip is nested inside a control of the same density. The dismiss button applies the same inset depth again inside the Chip's already-reduced height, and its trailing padding matches the resulting top and bottom space. The default single inset removes 4px overall; insetDepth double removes 8px overall and falls back to single at xs.",
3052
3055
  "Chip is designed only for primary surfaces and has no surface-context API."
3053
3056
  ],
3054
3057
  "responsiveBehavior": [
@@ -3075,10 +3078,18 @@
3075
3078
  },
3076
3079
  "api": {
3077
3080
  "props": {
3081
+ "insetDepth": {
3082
+ "type": "ControlInsetDepth",
3083
+ "required": false
3084
+ },
3078
3085
  "isInactive": {
3079
3086
  "type": "boolean",
3080
3087
  "required": false
3081
3088
  },
3089
+ "isInset": {
3090
+ "type": "boolean",
3091
+ "required": false
3092
+ },
3082
3093
  "label": {
3083
3094
  "type": "string",
3084
3095
  "required": true
@@ -3800,12 +3811,12 @@
3800
3811
  "tag": "ds-filter-menu",
3801
3812
  "name": "filter-menu",
3802
3813
  "title": "FilterMenu",
3803
- "summary": "Controlled two-pane filter select with menu-recipe category navigation, single- and multiple-choice, boolean, semantic relative-date and fixed-range filters, selected counts, and a clear action.",
3814
+ "summary": "Controlled two-pane filter select with menu-recipe category navigation, local option search for non-date categories, single- and multiple-choice, boolean, semantic relative-date and fixed-range filters, selected counts, and a clear action.",
3804
3815
  "intentStatus": "complete",
3805
3816
  "intent": {
3806
3817
  "audience": "general",
3807
3818
  "status": "stable",
3808
- "summary": "Controlled two-pane filter select with menu-recipe category navigation, single- and multiple-choice, boolean, semantic relative-date and fixed-range filters, selected counts, and a clear action.",
3819
+ "summary": "Controlled two-pane filter select with menu-recipe category navigation, local option search for non-date categories, single- and multiple-choice, boolean, semantic relative-date and fixed-range filters, selected counts, and a clear action.",
3809
3820
  "useWhen": [
3810
3821
  "A compact trigger must expose several filter families without turning the toolbar into many separate controls.",
3811
3822
  "Users need to move between persistent filter categories while editing the selected category in a second pane."
@@ -3835,17 +3846,20 @@
3835
3846
  "accessibility": [
3836
3847
  "The built-in select trigger exposes combobox semantics with a dialog popup, synchronizes expanded state, holds the pressed interaction wash without changing resting foreground while open, and restores focus after dismissal.",
3837
3848
  "The category pane is a vertical tab list. Arrow Up and Arrow Down wrap, Home and End jump, Arrow Right enters the option pane, and Arrow Left returns to the active category.",
3849
+ "Every non-date category begins with a labelled search field. Arrow Down and Arrow Up enter the first or last visible option, while Left and Right retain native text-caret behavior. Search matches option labels and descriptions without changing selected values.",
3838
3850
  "Escape and outside activation close the popup and restore trigger focus. Tab moves through option controls and closes only when it leaves the popup boundary.",
3839
- "Date filters expose Range and Relative tabs in a compact header. Relative presets use listbox semantics; the range calendar exposes a labelled grid, one tab stop, arrow-key day navigation, Home and End week navigation, and Page Up or Page Down month navigation.",
3851
+ "Date filters expose containerless Range and Relative tabs in a secondary-background header with 4px padding around the 32px medium control. Relative presets use listbox semantics; the range calendar exposes a labelled grid, one tab stop, arrow-key day navigation, Home and End week navigation, and Page Up or Page Down month navigation. After a range start is chosen, pointer hover and keyboard focus preview the possible inclusive range without changing selection semantics.",
3840
3852
  "When an external trigger is inside an open shadow tree, pass its HTMLElement through anchor so outside activation, focus return, and Tab continuation use the composed tree.",
3841
3853
  "The trigger count reports active filter categories. Multiple-choice category tags report individual selected criteria, while an applied Date category uses a visual dot because its value is singular. The default summary footer announces the total; the categories-clear footer recipe reserves a visually empty category-pane action row and exposes its divider and only Clear when criteria are active."
3842
3854
  ],
3843
3855
  "states": [
3844
- "The application owns filters, values, activeFilterId, and open. Replace controlled objects and arrays after dsChange, dsActiveFilterChange, dsClear, or dsClose.",
3856
+ "The application owns filters, values, matchModes, activeFilterId, and open. Replace controlled objects and arrays after dsChange, dsMatchModeChange, dsActiveFilterChange, dsClear, or dsClose.",
3845
3857
  "Single filters return a string, multiple filters return ordered string arrays, boolean filters return a boolean, and date filters return a serializable semantic string.",
3858
+ "Multiple filters expose a right-pane footer reading Limit results to any or all selected. any is the default OR mode. Activating the blue mode word requests the opposite controlled mode through dsMatchModeChange; the application owns the corresponding query semantics.",
3859
+ "Non-date option search is internal, scoped independently per category while the popup remains open, and reset after the popup closes. An unmatched query shows the configurable noResultsText empty state. Date uses its Relative and Range modes instead of option search.",
3846
3860
  "Date values are serializable semantic strings: relative:<preset> preserves a relative choice for future resolution and range:<start>/<end> preserves fixed inclusive ISO calendar dates. A legacy YYYY-MM-DD value is interpreted as a one-day range.",
3847
3861
  "Relative presets are Today, Yesterday, and the last 7, 14, 30, 60, or 90 inclusive calendar days. Applications resolve them against their current product date and time-zone policy by using resolveDateFilterRange from @ds-mo/ui/utils.",
3848
- "Range selection applies the first date immediately as a one-day range; a second activation completes an ordered inclusive range. A new activation after completion starts a replacement range.",
3862
+ "Range selection applies the first date immediately as a one-day range; while an end is pending, that selected start retains its bold treatment and hovering or focusing another day paints the rest of the provisional inclusive span faint without emitting a value. A second activation completes an ordered inclusive range and gives both edges the bold treatment. A new activation after completion starts a replacement range.",
3849
3863
  "Selection applies immediately and does not close the popup.",
3850
3864
  "Changing category replaces the option-pane subtree so checkbox and other option visuals mount in their new state instead of transitioning from the previous category's row state.",
3851
3865
  "The trigger reports how many filter categories have selections. footerLayout=summary adds a full-width selected-count footer only while values are selected; footerLayout=categories-clear always reserves the category-pane footer height while keeping its inactive divider hidden, then reveals the divider and only its left-aligned Clear action while values are selected."
@@ -3858,13 +3872,13 @@
3858
3872
  ],
3859
3873
  "frameworkCaveats": {
3860
3874
  "customElements": [
3861
- "Assign filters and values as JavaScript properties after the element is defined."
3875
+ "Assign filters, values, and matchModes as JavaScript properties after the element is defined."
3862
3876
  ],
3863
3877
  "react": [
3864
- "Pass filters and values as controlled props and handle onDsChange, onDsActiveFilterChange, onDsClear, and onDsClose."
3878
+ "Pass filters, values, and matchModes as controlled props and handle onDsChange, onDsMatchModeChange, onDsActiveFilterChange, onDsClear, and onDsClose."
3865
3879
  ],
3866
3880
  "angular": [
3867
- "Use property bindings for filters and values and event bindings for dsChange, dsActiveFilterChange, dsClear, and dsClose."
3881
+ "Use property bindings for filters, values, and matchModes and event bindings for dsChange, dsMatchModeChange, dsActiveFilterChange, dsClear, and dsClose."
3868
3882
  ]
3869
3883
  },
3870
3884
  "references": [
@@ -3944,6 +3958,10 @@
3944
3958
  "type": "string | undefined",
3945
3959
  "required": false
3946
3960
  },
3961
+ "matchModes": {
3962
+ "type": "FilterMenuMatchModes",
3963
+ "required": false
3964
+ },
3947
3965
  "menuLabel": {
3948
3966
  "type": "string",
3949
3967
  "required": false
@@ -3952,10 +3970,18 @@
3952
3970
  "type": "string",
3953
3971
  "required": false
3954
3972
  },
3973
+ "noResultsText": {
3974
+ "type": "string",
3975
+ "required": false
3976
+ },
3955
3977
  "open": {
3956
3978
  "type": "boolean",
3957
3979
  "required": false
3958
3980
  },
3981
+ "searchPlaceholder": {
3982
+ "type": "string",
3983
+ "required": false
3984
+ },
3959
3985
  "showSelectedCount": {
3960
3986
  "type": "boolean",
3961
3987
  "required": false
@@ -4006,6 +4032,10 @@
4006
4032
  "name": "dsClose",
4007
4033
  "detail": "void"
4008
4034
  },
4035
+ {
4036
+ "name": "dsMatchModeChange",
4037
+ "detail": "FilterMenuMatchModeChangeDetail"
4038
+ },
4009
4039
  {
4010
4040
  "name": "dsOpenChange",
4011
4041
  "detail": "boolean"
@@ -4028,7 +4058,9 @@
4028
4058
  "badge",
4029
4059
  "button-unfilled",
4030
4060
  "checkbox",
4061
+ "empty-state",
4031
4062
  "icon",
4063
+ "input",
4032
4064
  "tab-group",
4033
4065
  "tag",
4034
4066
  "text",
@@ -4210,10 +4242,12 @@
4210
4242
  ],
4211
4243
  "states": [
4212
4244
  "Every size applies one complete control-density recipe across frame height, inline padding, icon zones, text-container inset, gap, and radius; supporting error content follows the shared 4px field flow.",
4213
- "The normal field boundary uses the shared secondary inset border. Focus promotes it to the thicker bold-brand inset stroke, while error uses the thicker bold-negative inset stroke without changing geometry. Set hasBorder to false only in chrome that supplies enough surrounding structure; the control then remains borderless at rest, while focused, and while invalid, with semantics and supporting error copy unchanged.",
4245
+ "The normal field boundary uses the shared secondary inset border. Focus promotes it to the thicker bold-brand inset stroke, while error uses the thicker bold-negative inset stroke without changing geometry. Set hasBorder to false only in chrome that supplies enough surrounding structure; set hasInteractionFill to false when that containing chrome also owns hover and pressed feedback.",
4214
4246
  "Placeholder text is secondary at rest and quaternary while the editable field is focused because it becomes decorative once typing begins. Single-line placeholder and entered value text truncate with an ellipsis when the field is narrower than its content.",
4215
4247
  "Entered values use the parent surface's primary foreground; prefix icons, suffix content, and resting placeholder text use its secondary foreground.",
4216
4248
  "Search fields show a standard borderless CrossCircle icon action only while they contain a value. Clearing emits the empty value and restores focus to the native field.",
4249
+ "Search fields disable browser autocomplete history, automatic capitalization, autocorrection, and spellchecking by default so browser-owned suggestions do not compete with product-owned results. Consumers can explicitly provide autoComplete when a different native history behavior is required.",
4250
+ "Search fields used with owned result sets forward aria-controls and aria-activedescendant to the native field so keyboard focus can remain in the query while assistive technology tracks the active result.",
4217
4251
  "The suffix slot is for compact units or decorations. The optional leading icon is decorative and does not replace the field label.",
4218
4252
  "Use autoComplete, inputMode, and enterKeyHint to provide browser and virtual-keyboard hints without changing the value's semantic type.",
4219
4253
  "Number fields preserve native spinbutton semantics, keyboard stepping, and min/max constraint behavior while dsChange continues to report the native string value. Two borderless inset chevron actions split the available inner height, disable independently at their numeric bound, and restore focus to the spinbutton after pointer activation.",
@@ -4254,6 +4288,14 @@
4254
4288
  },
4255
4289
  "api": {
4256
4290
  "props": {
4291
+ "ariaActiveDescendant": {
4292
+ "type": "string | undefined",
4293
+ "required": false
4294
+ },
4295
+ "ariaControls": {
4296
+ "type": "string | undefined",
4297
+ "required": false
4298
+ },
4257
4299
  "ariaDescribedby": {
4258
4300
  "type": "string | undefined",
4259
4301
  "required": false
@@ -4302,6 +4344,10 @@
4302
4344
  "type": "boolean",
4303
4345
  "required": false
4304
4346
  },
4347
+ "hasInteractionFill": {
4348
+ "type": "boolean",
4349
+ "required": false
4350
+ },
4305
4351
  "icon": {
4306
4352
  "type": "string | undefined",
4307
4353
  "required": false
@@ -6691,13 +6737,12 @@
6691
6737
  },
6692
6738
  "dependencies": [
6693
6739
  "@ds-mo/ui",
6694
- "@ds-mo/tokens",
6695
- "@ds-mo/icons"
6740
+ "@ds-mo/tokens"
6696
6741
  ],
6697
6742
  "componentDependencies": [
6698
6743
  "button-unfilled",
6699
6744
  "divider",
6700
- "icon",
6745
+ "input",
6701
6746
  "text",
6702
6747
  "tooltip"
6703
6748
  ]
@@ -7538,6 +7583,7 @@
7538
7583
  "checkbox",
7539
7584
  "empty-state",
7540
7585
  "icon",
7586
+ "input",
7541
7587
  "loader",
7542
7588
  "text",
7543
7589
  "tooltip"
@@ -8811,6 +8857,7 @@
8811
8857
  "A missing, empty, inactive, or unknown selected value is invalid when enabled tabs exist; the component does not choose a fallback selection.",
8812
8858
  "Selection is singular and follows keyboard focus.",
8813
8859
  "Width follows the shared control contract: hug keeps the track content-sized, while fill occupies the parent width and distributes available space equally across selectable segments; dividers remain fixed-width separators.",
8860
+ "hasContainer defaults to true. Set it to false only when a parent surface owns the track background and boundary; the outer fill, border, and inset disappear while selected-pill, interaction, focus, density, and keyboard behavior remain unchanged.",
8814
8861
  "Small, medium, and large use the shared 24px, 32px, and 40px control-density recipes for the outer track. Each segment uses the same-size inset recipe at 20px, 28px, and 36px while preserving that density's typography, icon, gap, and label metrics.",
8815
8862
  "Use one consistent content variant across every selectable tab in a group.",
8816
8863
  "Omitted background is for primary and secondary surfaces; pass the faint context explicitly on faint surfaces.",
@@ -8855,6 +8902,10 @@
8855
8902
  "type": "TabBackground | undefined",
8856
8903
  "required": false
8857
8904
  },
8905
+ "hasContainer": {
8906
+ "type": "boolean",
8907
+ "required": false
8908
+ },
8858
8909
  "size": {
8859
8910
  "type": "TabGroupSize",
8860
8911
  "required": false
@@ -8902,12 +8953,12 @@
8902
8953
  "tag": "ds-table",
8903
8954
  "name": "table",
8904
8955
  "title": "Table",
8905
- "summary": "Semantic, controlled data table with durable visual primitives for cell geometry, grouping, sorting, multi-selection, sticky overflow, incremental loading, top-level pagination, and optional row virtualization.",
8956
+ "summary": "Semantic, controlled data table with durable visual primitives for cell geometry, wrapping multiple-Tag cells, grouping, sorting, multi-selection, sticky overflow, incremental loading, top-level pagination, and optional row virtualization.",
8906
8957
  "intentStatus": "complete",
8907
8958
  "intent": {
8908
8959
  "audience": "general",
8909
8960
  "status": "stable",
8910
- "summary": "Semantic, controlled data table with durable visual primitives for cell geometry, grouping, sorting, multi-selection, sticky overflow, incremental loading, top-level pagination, and optional row virtualization.",
8961
+ "summary": "Semantic, controlled data table with durable visual primitives for cell geometry, wrapping multiple-Tag cells, grouping, sorting, multi-selection, sticky overflow, incremental loading, top-level pagination, and optional row virtualization.",
8911
8962
  "useWhen": [
8912
8963
  "A structured dataset needs native row and column relationships, optional one-level grouping, or comparable values across records.",
8913
8964
  "An application needs controlled sorting, loaded-row selection, infinite loading, pagination, virtual row recycling, or opted-in table-owned data-mode and column controls while retaining ownership of the data query, catalog, and persistence.",
@@ -8942,15 +8993,16 @@
8942
8993
  "The rendered structure uses a native table, caption, column headers, row groups, and data cells; keep the caption non-empty. The native caption remains visually hidden as the table's accessible name. When caption visibility is enabled, a 48px header bar renders as component chrome outside the data scrollport. It defaults to a presentational caption title that does not duplicate the accessible name. Application-owned labeled controls supplied through the single named header slot replace that fallback and share one horizontal caption overflow row with table-owned actions inside the component-owned 8px inset. Table caption buttons keep pressed interaction paint without physically scaling. When columnCustomizer is enabled, the table adds a trailing Customize control named Customize table. Its label uses regular weight and its resting foreground remains neutral when hidden or reordered columns differ from the catalog default. The control is icon-label at typical widths and the icon-only Table menu button below 900px, where a tooltip preserves the Customize label. The always-icon-only table-variant control also exposes its label through a tooltip. Otherwise the header slot receives the complete content width.",
8943
8994
  "The data-mode switcher is the shared Menu of the table's supported infinite, pagination, and virtual modes. It uses an Ellipses trigger. The switcher is the final caption-bar action; when the column customizer is also present, a decorative vertical divider separates the two controls. dataMode remains controlled, and the application responds to change intent by supplying the matching records, pagination state, loading behavior, and query consequences. Escape, dismissal, and selection return focus to the trigger.",
8944
8995
  "The column customizer is the shared Menu of switch rows, not a table-owned dialog. Data columns can be shown, hidden, and reordered. Action columns and the selection checkbox never appear in the menu. The last remaining visible data column cannot be hidden, but it stays focusable so it can still be reordered. Escape and outside click restore focus to the trigger. Persistence stays in the application.",
8945
- "Sorting controls remain buttons inside column headers and expose the table's one controlled member-row sort through aria-sort. ds-table-sort in the toolbar trailing cluster is the matching menu of Data and Direction sections; it emits the same dsSortChange shape so header clicks and menu choices stay in sync. Grouping never adds a second sort indicator or header control; the application supplies groups in its fixed product order. Optional column help underlines the header label with the shared dotted decoration and shows ds-tooltip from that label; it does not add a second header control or replace the column name.",
8996
+ "Sorting controls remain buttons inside column headers and expose the table's one controlled member-row sort through aria-sort. ds-table-sort in the toolbar trailing cluster is the matching menu of Data and Direction sections; it emits the same dsSortChange shape so header clicks and menu choices stay in sync. Grouping never adds a second sort indicator or header control; ds-table-group controls the grouping data point and ascending or descending group-section order while the application supplies the resulting groups. Optional column help underlines the header label with the shared dotted decoration and shows ds-tooltip from that label; it does not add a second header control or replace the column name.",
8946
8997
  "Selection controls expose checkbox semantics and explicit row names; select-all affects selectable loaded rows only and preserves selected identities outside the loaded window. In virtual mode the supplied in-memory rows are that loaded set, including rows whose DOM is recycled. When grouping is active with multi-selection, each group section header also exposes a checkbox that selects or clears that group's selectable loaded rows.",
8947
8998
  "Interactive rows are focusable as native rows, activate with Enter or Space, and do not steal activation from their nested selection, action, overflow-menu, or primary-text link controls.",
8948
8999
  "Scrollable table regions become keyboard focusable and named only when overflow exists.",
8949
9000
  "Incremental loading, newly appended row counts, failures, and end-of-results transitions are announced through a polite status region without replacing visible state. In grouped tables, announcements name the independently loading group.",
9001
+ "Applications may pass their controlled literal search terms through highlightTerms after applying their own filtering. When TableSearch scopes the query, pass the same selected field identities through highlightFieldIds. A compound column maps its ordered headerSegments to primary, secondary-run, and tertiary-run data points; simple columns map their column ID to every owned text track. With no highlightFieldIds every text track remains eligible. Matching text is rendered with semantic mark elements, so the emphasis is identifiable independently of its faint-brand background and bold-brand foreground. Highlight markup preserves source order, the cell's complete accessible text, and does not create extra announcements.",
8950
9002
  "Static and infinite tables may show an optional result summary footer when displayedCount and totalCount are finite. Virtual mode shows a total-only summary and ignores displayedCount. Pagination mode instead renders a named Pagination control with a compact selected-size total, vertical divider, and page position; range changes are announced independently with complete phrasing. Unmodified Left and Right Arrow request the adjacent page while focus is inside a paginated table or on a containing page scroller that owns it; editable fields, choice controls, sliders, open menus, and modified key combinations retain their own keyboard behavior. A table-owned footer slot can replace summary copy, while footer-leading and footer-trailing remain available in the same compact-bar anatomy. Nested dialog footers are ignored."
8951
9003
  ],
8952
9004
  "states": [
8953
- "Columns, rows, groups, grouping, sorting, selected row IDs, collapsed group IDs, hiddenColumnIds, columnOrder, dataMode, pagination, displayedCount, totalCount, and incremental-loading state are controlled inputs. Events communicate intent and never mutate those inputs. The optional header is one composable table-local surface: the component owns its 48px chrome, 8px inset on every side, and sticky placement while the application owns the leading slot's internal layout, controls, labels, filtering behavior, and action handling. Opting into dataModeSwitcher and columnCustomizer adds their trailing Menu triggers and requires caption visibility. When both are present, Customize precedes a decorative divider and the data-mode trigger remains the final action. The Customize trigger keeps one stable label and neutral resting foreground whether or not hiddenColumnIds or columnOrder differ from the catalog default; the configured state remains visible inside the Menu. The table closes one trailing Menu before opening the other. The footer retains its compact-bar composition: application-owned leading status sits left while a controlled result summary or Pagination aligns right, before any trailing action. Content-sized tables remain natural for sparse or fixed-count results. height bounds the complete header, frame, and footer composition. fitViewport reserves the compact-state composition height in the nearest vertical scrollport while growing the visible table into that reservation as surrounding page chrome collapses.",
9005
+ "Columns, rows, groups, grouping, sorting, selected row IDs, collapsed group IDs, highlightTerms, highlightFieldIds, hiddenColumnIds, columnOrder, dataMode, pagination, displayedCount, totalCount, and incremental-loading state are controlled inputs. Events communicate intent and never mutate those inputs. The optional header is one composable table-local surface: the component owns its 48px chrome, 8px inset on every side, and sticky placement while the application owns the leading slot's internal layout, controls, labels, filtering behavior, and action handling. highlightTerms only marks matching table-owned text and never filters rows, changes query semantics, or highlights Tag labels. highlightFieldIds optionally narrows that marking to matching column IDs or compound header-segment sort keys. Opting into dataModeSwitcher and columnCustomizer adds their trailing Menu triggers and requires caption visibility. When both are present, Customize precedes a decorative divider and the data-mode trigger remains the final action. The Customize trigger keeps one stable label and neutral resting foreground whether or not hiddenColumnIds or columnOrder differ from the catalog default; the configured state remains visible inside the Menu. The table closes one trailing Menu before opening the other. The footer retains its compact-bar composition: application-owned leading status sits left while a controlled result summary or Pagination aligns right, before any trailing action. Content-sized tables remain natural for sparse or fixed-count results. height bounds the complete header, frame, and footer composition. fitViewport reserves the compact-state composition height in the nearest vertical scrollport while growing the visible table into that reservation as surrounding page chrome collapses.",
8954
9006
  "Grouping supports one level. The application supplies groups in a fixed product-defined order and supplies ordered member rows independently. Group section headers show an emphasized text-body-medium label followed by a middle dot and plain secondary loaded progress, for example Critical · 50 of 166. The loaded value comes from the supplied member rows and the total comes from totalCount. A localized countLabel total phrase remains available for the complete assistive progress announcement. Virtual mode shows totals only, for example Critical · 166, because there is no loaded window. Groups may declare an optional intent (brand, neutral, negative, warning, caution, positive) that paints an LTR gradient from the faint intent surface at the label edge into faint neutral at the trailing edge, plus a bold intent title color. Neutral groups remain solid faint neutral. Section separators are painted inside that viewport-width surface so translucent border tokens composite with each intent background. Internal sections keep their separators; a collapsed or empty section header yields its separator only when it is the table's final rendered item. A trailing visually neutral icon-only ButtonUnfilled uses the 24px md double-inset action recipe and toggles controlled collapsedGroupIds, showing ChevronUp while expanded and ChevronDown while collapsed. While any group is expanded, a ChevronDownUp action uses the xs sort-control recipe widened to a table-owned 24px lane and collapses every group. It appears at the inline-end edge of the trailing column declared with kind action when one exists; otherwise a button-hugging 24px by 16px medium-elevation surface floats at the visible scrollport's header edge so the action remains reachable while member columns scroll beneath it. With stickyHeader enabled, each contained section uses its one real section row as a native sticky header inside its real row-group boundary. The browser therefore owns pinning, push-off, scrolling, and resize layout in one pass without a duplicated lane, active-section state, transforms, or scroll-time geometry. Shared grid tracks retain exact header and member-cell alignment. The section surface also stays pinned to the visible horizontal scrollport and spans the smaller of the visible viewport or table width. Virtual grouped tables flatten headers and members into that same scrollport; expanding a section never introduces an inner scroller.",
8955
9007
  "When columnCustomizer is false, columns render in catalog order. When it is true, columns remains the catalog: hiddenColumnIds and columnOrder control visibility and data-column sequence, action columns stay last, cannot be hidden, and remain absent from the customizer Menu, and dsColumnsConfigChange reports the next hidden ids and data-column order without mutating those inputs. The customizer Menu live-applies show/hide and data-column reorder. The table does not persist preferences.",
8956
9008
  "An active member sort toggles only between ascending and descending; activating a different sortable label moves the one sorting state to that key. Applications may still clear the controlled sort state explicitly. Grouping does not introduce another interactive direction.",
@@ -8960,7 +9012,7 @@
8960
9012
  "When pagination enables Fit to page on a bounded table, the table proposes the number of complete top-level rows that fit below its column header. Grouped tables count group headers only; member rows never affect capacity. Selecting Fit captures that numeric snapshot. A changed fitIdentity requests one fresh snapshot for a new query shape, while viewport resizing alone does not change the active controlled page size.",
8961
9013
  "Rows opt into complete-row activation with interactive and emit dsRowActivate without owning navigation. Selection paints through the shared selected ::before layer; interactive hover and press paint through the shared ::after layer.",
8962
9014
  "Row selection owns the single sticky start lane. One explicitly sized application column can own the sticky end lane, or the start lane when selection is absent. Each sticky boundary owns one fixed divider and a row-clipped directional shadow that paints into the adjacent scrolling columns only while more inline content remains beyond that edge.",
8963
- "Cells accept scalar content, standard primary-and-secondary or dual-primary text primitives, declarative Tag, icon-only, icon-and-text, 16:9 Image, or ButtonUnfilled Action content, or explicit Empty and Blank absence values. Text objects may declare an optional href (and target) on the primary track only; the table renders a native anchor with the shared brand text-action treatment when the URL is safe, and leaves scalars unlinked. Standard secondary copy defaults to the secondary foreground and may declare a semantic Text color when the application data carries intent; an optional tertiary track uses the same subdued body-small recipe as secondary. Secondary and tertiary may also be a short list of colorable runs, rendered on one line with the table's middle-dot separator. Dual-primary copy keeps both tracks primary unless explicitly colored and does not gain a tertiary track. Body data cells share 8px outer padding; header and group rows keep their own geometry. Text tracks, including Empty, keep 4px inline padding so copy lines up with column-header labels; Tag and icon-only tracks stay on the 8px cell chrome alone. Icon-and-text cells (`kind: 'icon-text'`) place one md prefix icon beside the same copy stack as a text cell. The icon slot takes 2px padding on every side, then a 2px flex gap before the copy; text-track padding stays on the copy. Omit iconLabel when the glyph is decorative. 20px content (body-medium text, md icon, and the row checkbox) sits in a 24px track so it stays optically aligned with 24px Tag and Action content. Single-track text, selection, tag-only, icon-only, icon-and-text, Action, Empty, Blank, and 1-track Image cells resolve a 40px base contract while two-track cells grow to 62px and three-track cells grow to 84px. Tracks stack with a 2px gap. Wrapping primary on a 1-track cell uses that same rhythm: two wrapped lines share the 62px row and three wrapped lines share the 84px row. Wrapping secondary keeps primary on the first track and consumes later tracks: two secondary lines share the 84px row and three secondary lines share a 106px fourth track. Keep the same track count in every row of a table or group when those rows should share one height. Tag cells use the inset Tag recipe: md double-inset is a 24px control for tag-only and tag-with-text, while text-with-tag uses sm single-inset at 20px so the second-track pill fills the body-small slot. Action cells primarily use an icon-only Ellipses treatment, render a 24px small ButtonUnfilled, default to unbordered, and emit row, column, and action identities through dsCellAction. When an action cell declares items, that Ellipses trigger opens the shared ds-menu for commands, dividers, inactive rows, and destructive rows instead of emitting on click; choosing a command emits dsCellAction with that item's actionId. Omit items to keep a single-shot control. Image cells declare tracks 1, 2, or 3 so the 16:9 bordered preview fills that body-row content box (cell height minus 8px padding) and the column hugs the resulting width; omit tracks for the 1-track recipe, and keep image tracks aligned with the other cells in the table or group. Image cells fall back to an accessible placeholder when no source is supplied. Empty means the data applies but has no value and renders an em dash with localized assistive text; Blank means the data is not applicable and renders no content. Nullish values remain backward-compatible Empty values. Stable type and variant hooks keep every cell family independently styleable.",
9015
+ "Cells accept scalar content, standard primary-and-secondary or dual-primary text primitives, declarative Tag, wrapping multiple-Tag content, icon-only, icon-and-text, 16:9 Image, or ButtonUnfilled Action content, or explicit Empty and Blank absence values. Text objects may declare an optional href (and target) on the primary track only; the table renders a native anchor with the shared brand text-action treatment when the URL is safe, and leaves scalars unlinked. Standard secondary copy defaults to the secondary foreground and may declare a semantic Text color when the application data carries intent; an optional tertiary track uses the same subdued body-small recipe as secondary. Secondary and tertiary may also be a short list of colorable runs, rendered on one line with the table's middle-dot separator. Dual-primary copy keeps both tracks primary unless explicitly colored and does not gain a tertiary track. Body data cells share 8px outer padding; header and group rows keep their own geometry. Text tracks, including Empty, keep 4px inline padding so copy lines up with column-header labels; Tag and icon-only tracks stay on the 8px cell chrome alone. Icon-and-text cells (`kind: 'icon-text'`) place one md prefix icon beside the same copy stack as a text cell. The icon slot takes 2px padding on every side, then a 2px flex gap before the copy; text-track padding stays on the copy. Omit iconLabel when the glyph is decorative. 20px content (body-medium text, md icon, and the row checkbox) sits in a 24px track so it stays optically aligned with 24px Tag and Action content. Single-track text, selection, tag-only, icon-only, icon-and-text, Action, Empty, Blank, and 1-track Image cells resolve a 40px base contract while two-track cells grow to 62px and three-track cells grow to 84px. Every later track adds 22px, so four tracks resolve to 106px, five to 128px, and the sequence may continue. Tracks stack with a 2px gap. Wrapping primary on a 1-track cell uses that same rhythm: two wrapped lines share the 62px row and three wrapped lines share the 84px row. Wrapping secondary keeps primary on the first track and consumes later tracks: two secondary lines share the 84px row and three secondary lines share a 106px fourth track. Keep the same track count in every row of a table or group when those rows should share one height. Tag cells use the inset Tag recipe: md double-inset is a 24px control for tag-only and tag-with-text, while text-with-tag uses sm single-inset at 20px so the second-track pill fills the body-small slot. Multiple-Tag cells use `kind: 'tags'`, a positive `tracks` count, and small single-inset Tags that wrap naturally at the column edge. Their 2px block inset creates the 24px first track and each later wrapped line adds a 20px track plus the shared 2px gap. The tallest cell establishes the native row height, so all sibling cells match even at four, five, or more tracks; virtual tables use the declared count as the initial estimate and measure responsive wrapping after paint. Action cells primarily use an icon-only Ellipses treatment, render a 24px small ButtonUnfilled, default to unbordered, and emit row, column, and action identities through dsCellAction. When an action cell declares items, that Ellipses trigger opens the shared ds-menu for commands, dividers, inactive rows, and destructive rows instead of emitting on click; choosing a command emits dsCellAction with that item's actionId. Omit items to keep a single-shot control. Image cells declare tracks 1, 2, or 3 so the 16:9 bordered preview fills that body-row content box (cell height minus 8px padding) and the column hugs the resulting width; omit tracks for the 1-track recipe, and keep image tracks aligned with the other cells in the table or group. Image cells fall back to an accessible placeholder when no source is supplied. Empty means the data applies but has no value and renders an em dash with localized assistive text; Blank means the data is not applicable and renders no content. Nullish values remain backward-compatible Empty values. Stable type, variant, and track-count hooks keep every cell family independently styleable.",
8964
9016
  "The public @ds-mo/ui/table.css export is the authoritative zero-specificity visual recipe. Override its --ds-table-* properties or target its stable element classes for product-specific styling."
8965
9017
  ],
8966
9018
  "responsiveBehavior": [
@@ -8969,14 +9021,14 @@
8969
9021
  "stickyHeader follows the active vertical scroll owner: a maxHeight, height, or fitViewport table keeps its native header and group sections inside one bounded table scrollport, while a document-flow table retains a semantic native header and renders a sticky control header whose columns follow the body's native inline scroll timeline. Consumers set --ds-table-sticky-header-offset when page chrome occupies an unbounded document scrollport edge. When the 48px table header bar is visible, it sticks at that external offset and the column header stacks immediately below it.",
8970
9022
  "fitViewport uses viewportInsetBlockStart and viewportInsetBlockEnd to describe compact surrounding chrome and page gutters relative to the nearest vertical scroll owner. Before the table reaches that compact position, its host reserves the eventual height while the visible composition grows and vertical input remains owned by the outer page. Once settled, the internal table viewport becomes the vertical scroll owner. Bounded grouped tables use browser-native sticky section rows inside real block row-group boundaries, so scroll and resize do not run component JavaScript or trigger reactive section swaps. Document-flow tables retain the synchronized visual lane required by their separate horizontal scrollport.",
8971
9023
  "Without maxHeight the table grows the document and automatic lazy loading observes the browser viewport. Horizontal scrolling chains vertical wheel and trackpad movement to the page instead of trapping it.",
8972
- "Explicit column sizes establish the horizontal overflow width; unsized columns share remaining space. Set imageTracks on an image column to derive its fixed width from the matching 1-, 2-, or 3-track 16:9 image geometry plus table cell padding instead of copying a numeric width.",
9024
+ "Explicit column sizes establish the horizontal overflow width; unsized columns share remaining space. When every visible data column is explicitly sized, one internal presentational spacer absorbs unused inline space without stretching the final data column and collapses to zero when those widths introduce horizontal overflow. The spacer sits before trailing action and sticky-end lanes so those controls remain at the visible edge. Set imageTracks on an image column to derive its fixed width from the matching 1-, 2-, or 3-track 16:9 image geometry plus table cell padding instead of copying a numeric width.",
8973
9025
  "Prefer the named xs through xl column sizes, which resolve through TokoMo's table-column width tokens; numeric pixel sizes remain an escape hatch for exceptional application-owned widths.",
8974
- "Column headers use one 32px geometry. Body rows use a 40px single-track minimum with shared 8px cell padding; additional tracks grow downward. Image previews fill the same content box as their declared track count. The second text track and the third text track share one subdued body-small recipe so line 3 lines up with line 2.",
9026
+ "Column headers use one 32px geometry. Body rows use a 40px single-track minimum with shared 8px cell padding; every additional track adds 22px and grows the complete native row so sibling cells match. Image previews fill the same content box as their declared track count. Wrapping multiple-Tag cells may declare any positive track count. The second text track and the third text track share one subdued body-small recipe so line 3 lines up with line 2.",
8975
9027
  "Long content truncates to one line by default. Hover (or keyboard-focus a primary link) shows the omitted value in one table-owned tooltip when that track overflows. maxLines 2 or 3 wrap onto the named 2-track and 3-track row heights, then ellipsize with the same tooltip. wrap: true remains unlimited and does not show a truncation tooltip. Wrapping 1-track primary occupies the named 2-track and 3-track row heights instead of a private line-height scale. Wrapping secondary on a 2-track cell occupies the named 3-track row and a 106px fourth track for three lines."
8976
9028
  ],
8977
9029
  "frameworkCaveats": {
8978
9030
  "customElements": [
8979
- "Assign columns, rows, groups, grouping, sort, selectedRowIds, collapsedGroupIds, hiddenColumnIds, columnOrder, pagination, displayedCount, and totalCount through JavaScript properties rather than HTML attribute strings.",
9031
+ "Assign columns, rows, groups, grouping, sort, selectedRowIds, collapsedGroupIds, highlightTerms, highlightFieldIds, hiddenColumnIds, columnOrder, pagination, displayedCount, and totalCount through JavaScript properties rather than HTML attribute strings.",
8980
9032
  "dataMode=virtual recycles row DOM over the supplied in-memory rows or groups and requires height, maxHeight, or fitViewport. It does not fetch or paginate.",
8981
9033
  "When an action cell supplies items, the table opens one shared ds-menu from the Ellipses trigger; dsCellAction fires for the selected command, not for opening or closing the menu.",
8982
9034
  "When columnCustomizer is enabled, the Table trigger opens the same shared ds-menu of reorderable switch rows; toggling a switch or reordering a row emits dsColumnsConfigChange and does not close the menu.",
@@ -9133,6 +9185,14 @@
9133
9185
  "type": "string[]",
9134
9186
  "required": false
9135
9187
  },
9188
+ "highlightFieldIds": {
9189
+ "type": "string[]",
9190
+ "required": false
9191
+ },
9192
+ "highlightTerms": {
9193
+ "type": "string[]",
9194
+ "required": false
9195
+ },
9136
9196
  "infiniteModeLabel": {
9137
9197
  "type": "string",
9138
9198
  "required": false
@@ -9317,12 +9377,12 @@
9317
9377
  "tag": "ds-table-filter",
9318
9378
  "name": "table-filter",
9319
9379
  "title": "TableFilter",
9320
- "summary": "Standard table-toolbar Filter control that owns the shared trigger, filter menu UI, accessible defaults, and compact-caption behavior while the application controls data and values.",
9380
+ "summary": "Standard table-toolbar Filter control that owns the shared trigger, searchable non-date filter options, accessible defaults, and compact-caption behavior while the application controls data and values.",
9321
9381
  "intentStatus": "complete",
9322
9382
  "intent": {
9323
9383
  "audience": "general",
9324
9384
  "status": "stable",
9325
- "summary": "Standard table-toolbar Filter control that owns the shared trigger, filter menu UI, accessible defaults, and compact-caption behavior while the application controls data and values.",
9385
+ "summary": "Standard table-toolbar Filter control that owns the shared trigger, searchable non-date filter options, accessible defaults, and compact-caption behavior while the application controls data and values.",
9326
9386
  "useWhen": [
9327
9387
  "A table toolbar should expose the standard singular Filter control and shared filter-menu interaction.",
9328
9388
  "A product supplies filter definitions and controlled values but should not recreate the toolbar trigger, category navigation, or responsive treatment."
@@ -9352,12 +9412,14 @@
9352
9412
  "accessibility": [
9353
9413
  "The trigger is an icon-label combobox named Filter table unless a product aria-label supplies the table context. Compact caption widths preserve that accessible name after the visible label and chevron are omitted.",
9354
9414
  "The popup retains ds-filter-menu category navigation, option semantics, focus entry, dismissal, and focus return, and aligns its start edge with the trigger.",
9355
- "Localize label, menuLabel, categoriesLabel, and clearLabel together so visible and accessible wording remains consistent."
9415
+ "Localize label, menuLabel, categoriesLabel, clearLabel, searchPlaceholder, and noResultsText together so visible and accessible wording remains consistent."
9356
9416
  ],
9357
9417
  "states": [
9358
- "filters, values, and activeFilterId are controlled. dsChange, dsClear, and dsActiveFilterChange report intent without changing those inputs; the application applies query consequences and returns replacement values.",
9418
+ "filters, values, matchModes, and activeFilterId are controlled. dsChange, dsMatchModeChange, dsClear, and dsActiveFilterChange report intent without changing those inputs; the application applies query consequences and returns replacement values.",
9359
9419
  "The visible trigger label stays singular Filter without appending an active-count suffix. Active criteria promote only the visible label from secondary to primary, matching the other table caption controls without redefining generic button active semantics.",
9360
9420
  "The popup reserves a visually empty footer row inside the category pane for every state. Active criteria reveal its divider and only a left-aligned Clear action, without adding popup height or showing redundant selected-count copy; the option pane retains its full column.",
9421
+ "Every multiple-choice category exposes a right-pane footer where the blue any or all word toggles its controlled match mode. any is the default OR mode; the application applies the requested mode to its query.",
9422
+ "Every non-date category exposes a 40px secondary-background search header that filters its displayed option labels and descriptions without changing controlled filter values. Date retains only its Relative and Range header.",
9361
9423
  "Date categories use the shared compact-header Range and Relative experience. Persist relative values semantically and resolve them from the product's current date whenever rows or saved views are applied.",
9362
9424
  "Popup visibility follows the same mutable open and dsOpenChange contract as ds-filter-menu."
9363
9425
  ],
@@ -9367,13 +9429,13 @@
9367
9429
  ],
9368
9430
  "frameworkCaveats": {
9369
9431
  "customElements": [
9370
- "Assign filters, values, and activeFilterId as JavaScript properties. Replace controlled values in response to dsChange and dsClear."
9432
+ "Assign filters, values, matchModes, and activeFilterId as JavaScript properties. Replace controlled values and modes in response to dsChange, dsMatchModeChange, and dsClear."
9371
9433
  ],
9372
9434
  "react": [
9373
- "Keep filters and values in application state and replace values from the typed dsChange and dsClear events."
9435
+ "Keep filters, values, and matchModes in application state and replace them from the typed dsChange, dsMatchModeChange, and dsClear events."
9374
9436
  ],
9375
9437
  "angular": [
9376
- "Import the generated DsTableFilter adapter, bind filters and values, and handle dsChange, dsClear, and dsActiveFilterChange."
9438
+ "Import the generated DsTableFilter adapter, bind filters, values, and matchModes, and handle dsChange, dsMatchModeChange, dsClear, and dsActiveFilterChange."
9377
9439
  ]
9378
9440
  },
9379
9441
  "references": [
@@ -9413,14 +9475,26 @@
9413
9475
  "type": "string",
9414
9476
  "required": false
9415
9477
  },
9478
+ "matchModes": {
9479
+ "type": "FilterMenuMatchModes",
9480
+ "required": false
9481
+ },
9416
9482
  "menuLabel": {
9417
9483
  "type": "string | null",
9418
9484
  "required": false
9419
9485
  },
9486
+ "noResultsText": {
9487
+ "type": "string",
9488
+ "required": false
9489
+ },
9420
9490
  "open": {
9421
9491
  "type": "boolean",
9422
9492
  "required": false
9423
9493
  },
9494
+ "searchPlaceholder": {
9495
+ "type": "string",
9496
+ "required": false
9497
+ },
9424
9498
  "values": {
9425
9499
  "type": "FilterMenuValues",
9426
9500
  "required": false
@@ -9447,6 +9521,10 @@
9447
9521
  "name": "dsClose",
9448
9522
  "detail": "void"
9449
9523
  },
9524
+ {
9525
+ "name": "dsMatchModeChange",
9526
+ "detail": "FilterMenuMatchModeChangeDetail"
9527
+ },
9450
9528
  {
9451
9529
  "name": "dsOpenChange",
9452
9530
  "detail": "boolean"
@@ -9468,6 +9546,138 @@
9468
9546
  "filter-menu"
9469
9547
  ]
9470
9548
  },
9549
+ {
9550
+ "id": "component:ds-table-group",
9551
+ "tag": "ds-table-group",
9552
+ "name": "table-group",
9553
+ "title": "TableGroup",
9554
+ "summary": "Two-panel toolbar control for choosing one table grouping data point and the ascending or descending order of its group sections.",
9555
+ "intentStatus": "complete",
9556
+ "intent": {
9557
+ "audience": "general",
9558
+ "status": "stable",
9559
+ "summary": "Two-panel toolbar control for choosing one table grouping data point and the ascending or descending order of its group sections.",
9560
+ "useWhen": [
9561
+ "A table toolbar needs explicit control of one grouping level and its section order.",
9562
+ "Grouping data-point labels differ from compact table-header labels."
9563
+ ],
9564
+ "avoidWhen": [
9565
+ "The table is not groupable.",
9566
+ "The application expects the component to rearrange rows or create group sections internally."
9567
+ ],
9568
+ "alternatives": [
9569
+ {
9570
+ "when": "The choice is one submitted form value with no dependent order pane.",
9571
+ "component": "component:ds-select",
9572
+ "reason": "Select owns form-value semantics rather than table grouping state."
9573
+ }
9574
+ ],
9575
+ "commonlyComposedWith": [
9576
+ "component:ds-table",
9577
+ "component:ds-table-toolbar",
9578
+ "component:ds-table-filter",
9579
+ "component:ds-table-sort"
9580
+ ],
9581
+ "patterns": [
9582
+ "pattern:menu-trigger"
9583
+ ],
9584
+ "accessibility": [
9585
+ "The trigger opens a named non-modal dialog. Data and Order are independently named single-selection listboxes.",
9586
+ "Up and Down move within the focused pane. Right moves from Data to Order when a group is active, Left returns to the selected Data row, and Escape closes the dialog and restores trigger focus.",
9587
+ "The right pane remains present before a group is active as one complete empty state without the Order heading, and explains that a group must be selected."
9588
+ ],
9589
+ "states": [
9590
+ "options and grouping are controlled. dsGroupChange reports a complete TableGroupingState and dsClear requests null grouping without mutating either input.",
9591
+ "Selecting a new data point starts its order at ascending. Re-selecting the active data point preserves its direction.",
9592
+ "Selecting a data point or direction applies immediately and leaves the dialog open so the other pane can be changed."
9593
+ ],
9594
+ "responsiveBehavior": [
9595
+ "Use in the trailing region of ds-table-toolbar.",
9596
+ "The trigger uses the shared caption-control button behavior and becomes icon-only in compact named table containers.",
9597
+ "Both panes remain present and their choice lists scroll within the collision-constrained popup."
9598
+ ],
9599
+ "frameworkCaveats": {
9600
+ "customElements": [
9601
+ "Assign options and grouping as JavaScript properties and replace grouping from dsGroupChange or dsClear."
9602
+ ],
9603
+ "react": [
9604
+ "Keep grouping in application state and replace it from dsGroupChange; set it to null from dsClear."
9605
+ ],
9606
+ "angular": [
9607
+ "Import the generated DsTableGroup adapter and bind options and grouping as properties."
9608
+ ]
9609
+ },
9610
+ "references": [
9611
+ {
9612
+ "label": "Review states",
9613
+ "path": "src/wc/components/TableGroup/TableGroup.stories.ts"
9614
+ },
9615
+ {
9616
+ "label": "Toolbar composition owner",
9617
+ "path": "src/wc/components/TableToolbar/TableToolbar.agent.json"
9618
+ }
9619
+ ]
9620
+ },
9621
+ "api": {
9622
+ "props": {
9623
+ "ariaLabel": {
9624
+ "type": "string | null",
9625
+ "required": false
9626
+ },
9627
+ "clearLabel": {
9628
+ "type": "string",
9629
+ "required": false
9630
+ },
9631
+ "emptyMessage": {
9632
+ "type": "string",
9633
+ "required": false
9634
+ },
9635
+ "grouping": {
9636
+ "type": "TableGroupingState | null",
9637
+ "required": false
9638
+ },
9639
+ "open": {
9640
+ "type": "boolean",
9641
+ "required": false
9642
+ },
9643
+ "options": {
9644
+ "type": "TableGroupOption[]",
9645
+ "required": false
9646
+ }
9647
+ },
9648
+ "events": [
9649
+ {
9650
+ "name": "dsClear",
9651
+ "detail": "void"
9652
+ },
9653
+ {
9654
+ "name": "dsGroupChange",
9655
+ "detail": "TableGroupingState"
9656
+ },
9657
+ {
9658
+ "name": "dsOpenChange",
9659
+ "detail": "boolean"
9660
+ }
9661
+ ],
9662
+ "slots": []
9663
+ },
9664
+ "exports": {
9665
+ "customElement": "ds-table-group",
9666
+ "react": "DsTableGroup",
9667
+ "vue": "DsTableGroup",
9668
+ "angular": "DsTableGroup"
9669
+ },
9670
+ "dependencies": [
9671
+ "@ds-mo/ui",
9672
+ "@ds-mo/tokens"
9673
+ ],
9674
+ "componentDependencies": [
9675
+ "button-unfilled",
9676
+ "empty-state",
9677
+ "input",
9678
+ "text"
9679
+ ]
9680
+ },
9471
9681
  {
9472
9682
  "id": "component:ds-table-saved-views",
9473
9683
  "tag": "ds-table-saved-views",
@@ -9616,6 +9826,148 @@
9616
9826
  "select"
9617
9827
  ]
9618
9828
  },
9829
+ {
9830
+ "id": "component:ds-table-search",
9831
+ "tag": "ds-table-search",
9832
+ "name": "table-search",
9833
+ "title": "TableSearch",
9834
+ "summary": "Controlled table-search editor with slash-invoked field scoping, removable inset field Chips, and an input-focused listbox keyboard model.",
9835
+ "intentStatus": "complete",
9836
+ "intent": {
9837
+ "audience": "general",
9838
+ "status": "stable",
9839
+ "summary": "Controlled table-search editor with slash-invoked field scoping, removable inset field Chips, and an input-focused listbox keyboard model.",
9840
+ "useWhen": [
9841
+ "A data-table search needs optional field-specific scopes without replacing the application's filtering logic.",
9842
+ "People should be able to add one or more searchable data points through a slash command while continuing to type one free-text query."
9843
+ ],
9844
+ "avoidWhen": [
9845
+ "A plain global text search is sufficient; use Input with type search.",
9846
+ "The choices are persistent filters with independent values; use TableFilter or Select instead.",
9847
+ "The component is expected to inspect records, build a search index, or filter rows internally."
9848
+ ],
9849
+ "commonlyComposedWith": [
9850
+ "component:ds-table",
9851
+ "component:ds-table-toolbar",
9852
+ "component:ds-chip",
9853
+ "component:ds-button-unfilled",
9854
+ "component:ds-icon"
9855
+ ],
9856
+ "accessibility": [
9857
+ "The native search input remains the one Tab stop and exposes combobox, expanded, controls, and active-descendant relationships to the field listbox.",
9858
+ "Typing slash opens the field listbox without inserting slash into the table query. Text typed while it is open filters data points by complete label, Up and Down change the active match, Enter selects it, Escape closes it, and Left and Right retain native text-cursor behavior because focus never leaves the input. Backspace edits the field-picker query first and closes the listbox when that query is empty.",
9859
+ "The query disables browser autocomplete history, automatic capitalization, autocorrection, and spellchecking so browser-owned suggestions never obscure the product-owned field menu or table results.",
9860
+ "Selected field Chips have individually labeled remove actions and are also described by the search input. Polite announcements report additions, removals, and clearing without duplicating the visible query.",
9861
+ "The slash suffix is a labeled double-inset md button excluded from sequential keyboard navigation; the search input exposes the same action through aria-keyshortcuts and its description.",
9862
+ "The clear action removes both free text and every selected field. It restores focus to the search input; each Chip's own remove action remains scoped to that field."
9863
+ ],
9864
+ "states": [
9865
+ "value and selectedFieldIds are controlled. columns supplies the same table catalog used by Table and TableSort; dataLabel provides the complete out-of-context name while header and header segment label may remain compact. dsChange reports query edits, dsFieldsChange reports the next ordered field identities, and dsClear reports a complete clear. The component never filters rows or mutates consumer inputs.",
9866
+ "The field menu excludes already-selected identities and closes after one selection. Typing slash again reopens the remaining fields so multiple scopes can be added.",
9867
+ "Selected scopes render as neutral md Chips using the double-inset recipe so they remain 24px high inside the 32px md search control and each can be removed directly.",
9868
+ "Backspace edits a non-empty field-picker query, then closes the open slash listbox when that query is empty. When the table query is empty and the listbox is already closed, the next Backspace removes the last selected field. Ordinary Backspace edits table query text when the listbox is closed.",
9869
+ "Duplicate, blank, and unknown field identities are ignored for presentation. Selected fields preserve the consumer's order.",
9870
+ "Inactive search leaves the tab order, closes the field listbox, and does not emit query or field changes."
9871
+ ],
9872
+ "responsiveBehavior": [
9873
+ "The control fills the available inline size supplied by the table toolbar search slot. Selected Chips and the editable query share one horizontal editor lane so the md control does not grow vertically.",
9874
+ "The field popup enters the top layer, aligns its first choice cell with the search control, flips or clamps to the viewport or nearest overlay boundary, and scrolls internally when its catalog is taller than available space.",
9875
+ "Long selected field labels truncate inside their Chips while the input remains available at the inline end of the editor lane. Both suffix actions resolve to the same 24px height as selected Chips. Clear follows the standard md Input recipe—a non-inset sm icon button—while slash is a double-inset md label button. Slash remains rightmost; when query text exposes Clear, a vertical divider separates the two actions."
9876
+ ],
9877
+ "frameworkCaveats": {
9878
+ "customElements": [
9879
+ "Assign columns and selectedFieldIds through JavaScript properties and replace controlled values from dsChange and dsFieldsChange.",
9880
+ "Keep field IDs aligned with the application search index; the component treats IDs as opaque values."
9881
+ ],
9882
+ "react": [
9883
+ "Pass new array references for columns and selectedFieldIds and update controlled state from onDsChange and onDsFieldsChange."
9884
+ ],
9885
+ "angular": [
9886
+ "Import DsTableSearch, bind columns, selectedFieldIds, and value, then update application signals from dsChange and dsFieldsChange."
9887
+ ]
9888
+ },
9889
+ "references": [
9890
+ {
9891
+ "label": "Storybook interaction states",
9892
+ "path": "src/wc/components/TableSearch/TableSearch.stories.ts"
9893
+ },
9894
+ {
9895
+ "label": "Toolbar composition owner",
9896
+ "path": "src/wc/components/TableToolbar/TableToolbar.agent.json"
9897
+ }
9898
+ ]
9899
+ },
9900
+ "api": {
9901
+ "props": {
9902
+ "ariaLabel": {
9903
+ "type": "string",
9904
+ "required": false
9905
+ },
9906
+ "clearLabel": {
9907
+ "type": "string",
9908
+ "required": false
9909
+ },
9910
+ "columns": {
9911
+ "type": "TableColumn[]",
9912
+ "required": false
9913
+ },
9914
+ "fieldMenuLabel": {
9915
+ "type": "string",
9916
+ "required": false
9917
+ },
9918
+ "isInactive": {
9919
+ "type": "boolean",
9920
+ "required": false
9921
+ },
9922
+ "placeholder": {
9923
+ "type": "string",
9924
+ "required": false
9925
+ },
9926
+ "selectedFieldIds": {
9927
+ "type": "string[]",
9928
+ "required": false
9929
+ },
9930
+ "value": {
9931
+ "type": "string",
9932
+ "required": false
9933
+ }
9934
+ },
9935
+ "events": [
9936
+ {
9937
+ "name": "dsChange",
9938
+ "detail": "string"
9939
+ },
9940
+ {
9941
+ "name": "dsClear",
9942
+ "detail": "void"
9943
+ },
9944
+ {
9945
+ "name": "dsFieldsChange",
9946
+ "detail": "TableSearchFieldsChangeDetail"
9947
+ }
9948
+ ],
9949
+ "slots": []
9950
+ },
9951
+ "exports": {
9952
+ "customElement": "ds-table-search",
9953
+ "react": "DsTableSearch",
9954
+ "vue": "DsTableSearch",
9955
+ "angular": "DsTableSearch"
9956
+ },
9957
+ "dependencies": [
9958
+ "@ds-mo/ui",
9959
+ "@ds-mo/tokens",
9960
+ "@ds-mo/icons"
9961
+ ],
9962
+ "componentDependencies": [
9963
+ "button-unfilled",
9964
+ "chip",
9965
+ "divider",
9966
+ "empty-state",
9967
+ "icon",
9968
+ "text"
9969
+ ]
9970
+ },
9619
9971
  {
9620
9972
  "id": "component:ds-table-sort",
9621
9973
  "tag": "ds-table-sort",
@@ -9756,6 +10108,7 @@
9756
10108
  "component:ds-divider",
9757
10109
  "component:ds-input",
9758
10110
  "component:ds-table-filter",
10111
+ "component:ds-table-group",
9759
10112
  "component:ds-select",
9760
10113
  "component:ds-table-sort",
9761
10114
  "component:ds-button-unfilled"
@@ -9769,24 +10122,24 @@
9769
10122
  "states": [
9770
10123
  "The component owns layout only. It never mutates slotted control props, values, menus, loading, persistence, or consequences. Use ds-table-saved-views and ds-table-filter when those interactions need the shared CompoMo behavior while application data and persistence remain external.",
9771
10124
  "Buttons in the toolbar keep their hover and pressed interaction paint without physically scaling, so pointer feedback does not disturb the stable caption geometry.",
9772
- "The start cluster is followed by a decorative vertical divider, then Search, optional leading controls, and one trailing action cluster. The start cluster and divider hide when nothing is projected. Search is a dedicated slot that hides when nothing is projected. Empty leading or trailing clusters add no placeholder chrome. Search is the only toolbar region that shrinks; all action controls retain their control geometry and align directly before the table-owned actions.",
10125
+ "The start cluster is followed by a decorative vertical divider, then Search, optional leading controls, and one trailing action cluster. The start cluster and divider hide when nothing is projected. Search is a dedicated slot that hides when nothing is projected and grows to consume available row space. Empty leading or trailing clusters add no placeholder chrome. Search is the only toolbar region that grows and shrinks; all action controls retain their control geometry and align directly before the table-owned actions.",
9773
10126
  "Column customizer and data-mode switching stay table-owned caption actions. Do not recreate those menus in the toolbar. When slotted into a table header, the table caption owns overflow for the complete toolbar and table-owned action row."
9774
10127
  ],
9775
10128
  "responsiveBehavior": [
9776
10129
  "The start cluster, search, trailing Filter/Sort/Group, and table caption trailing actions stay on one line. Saved views hug their current trigger content up to the compact menu-width token rather than reserving that full width; long names truncate while the dirty dot stays visible. Filter, Sort, and Group triggers cap at the same token, and Sort and Group popups keep that compact menu-width floor. A standalone toolbar owns its horizontal scrolling; inside a table, the complete caption row is the single overflow owner so table-owned actions never remain pinned over scrolling toolbar controls.",
9777
- "Inside a named ds-table container narrower than 900px, Search retains its standard maximum width and flexes smaller only when the complete row needs space. ds-table-filter and ds-table-sort omit their labels and chevrons, and Group controls explicitly opted into collapseLabel become icon-only; each exposes its label through a hover and keyboard-focus tooltip. Empty leading and trailing slot groups do not add spacing. Active filtering or grouping promotes the prefix icon to primary. Sort keeps resting secondary chrome. Table-owned Customize also becomes the icon-only Table menu button at that width with the same tooltip behavior.",
10130
+ "Search consumes the row space left between fixed control groups and flexes smaller when the complete row needs space. Inside a named ds-table container narrower than 900px, ds-table-filter, ds-table-group, and ds-table-sort omit their labels and chevrons; each exposes its label through a hover and keyboard-focus tooltip. Empty leading and trailing slot groups do not add spacing. Active filtering promotes its prefix icon to primary. Group and Sort keep resting secondary chrome. Table-owned Customize also becomes the icon-only Table menu button at that width with the same tooltip behavior.",
9778
10131
  "The scrollbar is visually suppressed without removing touch, trackpad, mouse-wheel, or keyboard scrolling from the overflow container.",
9779
10132
  "Trailing controls remain grouped after leading controls; the toolbar does not collapse controls into an application-specific overflow menu."
9780
10133
  ],
9781
10134
  "frameworkCaveats": {
9782
10135
  "customElements": [
9783
- "Project saved views through slot=start, search through slot=search, additional left-side middle controls through slot=leading, and ds-table-filter, Group, and ds-table-sort through slot=trailing. Set collapseLabel on the Group control and provide contextual accessible names when Table controls is insufficient."
10136
+ "Project saved views through slot=start, search through slot=search, additional left-side middle controls through slot=leading, and ds-table-filter, ds-table-group, and ds-table-sort through slot=trailing. Provide contextual accessible names when Table controls is insufficient."
9784
10137
  ],
9785
10138
  "react": [
9786
- "Set slot=start, slot=search, slot=leading, or slot=trailing on each child control. Use ds-table-filter for the standard Filter recipe, opt Group into collapseLabel, and keep values and event handlers in the application."
10139
+ "Set slot=start, slot=search, slot=leading, or slot=trailing on each child control. Use ds-table-filter and ds-table-group for the standard Filter and Group recipes, and keep values and event handlers in the application."
9787
10140
  ],
9788
10141
  "angular": [
9789
- "Set slot=start, slot=search, slot=leading, or slot=trailing on each child control, use DsTableFilter for the standard Filter recipe, opt Group into collapseLabel, and import the generated adapters."
10142
+ "Set slot=start, slot=search, slot=leading, or slot=trailing on each child control, use DsTableFilter and DsTableGroup for the standard Filter and Group recipes, and import the generated adapters."
9790
10143
  ]
9791
10144
  },
9792
10145
  "references": [