@ds-mo/ui 14.15.1 → 14.17.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 (259) hide show
  1. package/dist/.package-ready.json +1 -1
  2. package/dist/agent-patterns.json +3 -3
  3. package/dist/agent.json +317 -24
  4. package/dist/angular/ds-button-unfilled.d.ts +1 -1
  5. package/dist/angular/ds-button-unfilled.js +3 -3
  6. package/dist/angular/ds-filter-menu.d.ts +1 -1
  7. package/dist/angular/ds-filter-menu.js +3 -3
  8. package/dist/angular/ds-select.d.ts +1 -1
  9. package/dist/angular/ds-select.js +3 -3
  10. package/dist/angular/ds-table-filter.d.ts +44 -0
  11. package/dist/angular/ds-table-filter.js +57 -0
  12. package/dist/angular/ds-table-sort.d.ts +16 -0
  13. package/dist/angular/ds-table-sort.js +43 -0
  14. package/dist/angular/index.d.ts +1 -1
  15. package/dist/angular/index.js +2 -0
  16. package/dist/angular/proxies.d.ts +2 -0
  17. package/dist/angular/proxies.js +2 -0
  18. package/dist/components/ds-agent-activity.js +1 -1
  19. package/dist/components/ds-agent-questionnaire.js +1 -1
  20. package/dist/components/ds-agent-response.js +1 -1
  21. package/dist/components/ds-agent-source-list.js +1 -1
  22. package/dist/components/ds-agent-tool-call.js +1 -1
  23. package/dist/components/ds-attachment-list.js +1 -1
  24. package/dist/components/ds-badge.js +1 -1
  25. package/dist/components/ds-banner.js +1 -1
  26. package/dist/components/ds-banner.js.map +1 -1
  27. package/dist/components/ds-bar-action.js +1 -1
  28. package/dist/components/ds-bar-action.js.map +1 -1
  29. package/dist/components/ds-bar-nav.js +1 -1
  30. package/dist/components/ds-bar-title.js +1 -1
  31. package/dist/components/ds-bar-workflow.js +1 -1
  32. package/dist/components/ds-bar-workflow.js.map +1 -1
  33. package/dist/components/ds-breadcrumb.js +1 -1
  34. package/dist/components/ds-button-filled.js +1 -1
  35. package/dist/components/ds-button-unfilled.js +1 -1
  36. package/dist/components/ds-card-chart.js +1 -1
  37. package/dist/components/ds-card-chart.js.map +1 -1
  38. package/dist/components/ds-card-overview.js +1 -1
  39. package/dist/components/ds-card-overview.js.map +1 -1
  40. package/dist/components/ds-card-setting.js +1 -1
  41. package/dist/components/ds-card-setting.js.map +1 -1
  42. package/dist/components/ds-chart-legend.js +1 -1
  43. package/dist/components/ds-chart-legend.js.map +1 -1
  44. package/dist/components/ds-chart.js +1 -1
  45. package/dist/components/ds-chart.js.map +1 -1
  46. package/dist/components/ds-checkbox.js +1 -1
  47. package/dist/components/ds-chip.js +1 -1
  48. package/dist/components/ds-chip.js.map +1 -1
  49. package/dist/components/ds-code-block.js +1 -1
  50. package/dist/components/ds-conversation-list-item.js +1 -1
  51. package/dist/components/ds-conversation-list-item.js.map +1 -1
  52. package/dist/components/ds-conversation-list-section.js +1 -1
  53. package/dist/components/ds-empty-state.js +1 -1
  54. package/dist/components/ds-field.js +1 -1
  55. package/dist/components/ds-filter-menu.js +1 -1
  56. package/dist/components/ds-filter-menu.js.map +1 -1
  57. package/dist/components/ds-input.js +1 -1
  58. package/dist/components/ds-loader.js +1 -1
  59. package/dist/components/ds-markdown.js +1 -1
  60. package/dist/components/ds-menu.js +1 -1
  61. package/dist/components/ds-message-actions.js +1 -1
  62. package/dist/components/ds-message-actions.js.map +1 -1
  63. package/dist/components/ds-message-composer.js +1 -1
  64. package/dist/components/ds-message-composer.js.map +1 -1
  65. package/dist/components/ds-message-scroller.js +1 -1
  66. package/dist/components/ds-message-scroller.js.map +1 -1
  67. package/dist/components/ds-message.js +1 -1
  68. package/dist/components/ds-mobile-bar-nav.js +1 -1
  69. package/dist/components/ds-mobile-header.js +1 -1
  70. package/dist/components/ds-mobile-section-switcher.js +1 -1
  71. package/dist/components/ds-mobile-sheet-nav.js +1 -1
  72. package/dist/components/ds-modal.js +1 -1
  73. package/dist/components/ds-pagination.js +1 -1
  74. package/dist/components/ds-panel-nav.js +1 -1
  75. package/dist/components/ds-panel-sub-nav.js +1 -1
  76. package/dist/components/ds-panel-sub-nav.js.map +1 -1
  77. package/dist/components/ds-panel-tool-header.js +1 -1
  78. package/dist/components/ds-panel-tool-search.js +1 -1
  79. package/dist/components/ds-panel-tool-search.js.map +1 -1
  80. package/dist/components/ds-panel-tools.js +1 -1
  81. package/dist/components/ds-paper-texture.js +1 -1
  82. package/dist/components/ds-radio.js +1 -1
  83. package/dist/components/ds-scroll-overlay.js +1 -1
  84. package/dist/components/ds-scroll-overlay.js.map +1 -1
  85. package/dist/components/ds-select.js +1 -1
  86. package/dist/components/ds-shell-app.js +1 -1
  87. package/dist/components/ds-shell-app.js.map +1 -1
  88. package/dist/components/ds-shell-page.js +1 -1
  89. package/dist/components/ds-shell-tools.js +1 -1
  90. package/dist/components/ds-skeleton.js +1 -1
  91. package/dist/components/ds-slider.js +1 -1
  92. package/dist/components/ds-slider.js.map +1 -1
  93. package/dist/components/ds-swatch-picker.js +1 -1
  94. package/dist/components/ds-switch.js +1 -1
  95. package/dist/components/ds-tab-group.js +1 -1
  96. package/dist/components/ds-table-filter.d.ts +11 -0
  97. package/dist/components/ds-table-filter.js +2 -0
  98. package/dist/components/ds-table-filter.js.map +1 -0
  99. package/dist/components/ds-table-saved-views.js +1 -1
  100. package/dist/components/ds-table-saved-views.js.map +1 -1
  101. package/dist/components/ds-table-sort.d.ts +11 -0
  102. package/dist/components/ds-table-sort.js +2 -0
  103. package/dist/components/ds-table-sort.js.map +1 -0
  104. package/dist/components/ds-table-toolbar.js +1 -1
  105. package/dist/components/ds-table-toolbar.js.map +1 -1
  106. package/dist/components/ds-table.js +1 -1
  107. package/dist/components/ds-table.js.map +1 -1
  108. package/dist/components/ds-tag.js +1 -1
  109. package/dist/components/ds-text.js +1 -1
  110. package/dist/components/ds-toast.js +1 -1
  111. package/dist/components/ds-toast.js.map +1 -1
  112. package/dist/components/ds-tooltip-chart.js +1 -1
  113. package/dist/components/ds-tooltip.js +1 -1
  114. package/dist/components/ds-typing-indicator.js +1 -1
  115. package/dist/components/index.js +1 -1
  116. package/dist/components/index.js.map +1 -1
  117. package/dist/components/p-23u3lIr1.js +2 -0
  118. package/dist/components/{p-DLkNcCY0.js.map → p-23u3lIr1.js.map} +1 -1
  119. package/dist/components/{p-C1q-tq3U.js → p-7tZx4ukz.js} +2 -2
  120. package/dist/components/{p-DfyfrfHL.js → p-Asi9h3pa.js} +2 -2
  121. package/dist/components/{p-DfyfrfHL.js.map → p-Asi9h3pa.js.map} +1 -1
  122. package/dist/components/{p-C5TrNd31.js → p-B0PEg5RF.js} +2 -2
  123. package/dist/components/{p-C5TrNd31.js.map → p-B0PEg5RF.js.map} +1 -1
  124. package/dist/components/p-BFSLT0yc.js +2 -0
  125. package/dist/components/p-BFSLT0yc.js.map +1 -0
  126. package/dist/components/{p-DZFilC--.js → p-BGXqFq2C.js} +2 -2
  127. package/dist/components/{p-Rfpd5mWO.js → p-BHDkJmrC.js} +2 -2
  128. package/dist/components/{p-Rfpd5mWO.js.map → p-BHDkJmrC.js.map} +1 -1
  129. package/dist/components/{p-Cyw9odJX.js → p-BHz78C8h.js} +2 -2
  130. package/dist/components/{p-Cyw9odJX.js.map → p-BHz78C8h.js.map} +1 -1
  131. package/dist/components/{p-Dcnd5ZX5.js → p-BKp__CQX.js} +2 -2
  132. package/dist/components/{p-V2ywPfsR.js → p-BVlfQ8xZ.js} +2 -2
  133. package/dist/components/{p-V2ywPfsR.js.map → p-BVlfQ8xZ.js.map} +1 -1
  134. package/dist/components/p-BdnQv7Zl.js +2 -0
  135. package/dist/components/p-BdnQv7Zl.js.map +1 -0
  136. package/dist/components/{p-Dsn1RCS5.js → p-Be1sY58w.js} +2 -2
  137. package/dist/components/{p-Dsn1RCS5.js.map → p-Be1sY58w.js.map} +1 -1
  138. package/dist/components/p-Bh67XbfB.js +2 -0
  139. package/dist/components/{p-BzLnSwG9.js.map → p-Bh67XbfB.js.map} +1 -1
  140. package/dist/components/{p-Btxwp4lJ.js → p-BhYWdbEp.js} +2 -2
  141. package/dist/components/{p-Btxwp4lJ.js.map → p-BhYWdbEp.js.map} +1 -1
  142. package/dist/components/{p-D1Nqlrrl.js → p-Bn8NryHK.js} +2 -2
  143. package/dist/components/{p-D1Nqlrrl.js.map → p-Bn8NryHK.js.map} +1 -1
  144. package/dist/components/{p-B80NfEqc.js → p-C0X2zKbB.js} +2 -2
  145. package/dist/components/{p-Ct-m0I6U.js → p-C4TgWJi9.js} +2 -2
  146. package/dist/components/p-CKmfuK7k.js +2 -0
  147. package/dist/components/p-CKmfuK7k.js.map +1 -0
  148. package/dist/components/{p-DTMxwYQj.js → p-CMFvaY05.js} +2 -2
  149. package/dist/components/{p-PzI11fs8.js → p-CzcWZiH-.js} +2 -2
  150. package/dist/components/{p-PzI11fs8.js.map → p-CzcWZiH-.js.map} +1 -1
  151. package/dist/components/{p-BagXfn1G.js → p-D1YhYulL.js} +2 -2
  152. package/dist/components/{p-BzObtSlo.js → p-D2z2DgtX.js} +2 -2
  153. package/dist/components/{p-BzObtSlo.js.map → p-D2z2DgtX.js.map} +1 -1
  154. package/dist/components/{p-BXPQmp7q.js → p-D4K9CE8a.js} +2 -2
  155. package/dist/components/{p-DcPVSNDr.js → p-D8Qd6gkf.js} +2 -2
  156. package/dist/components/{p-DcPVSNDr.js.map → p-D8Qd6gkf.js.map} +1 -1
  157. package/dist/components/{p-BHjw0x3L.js → p-DAqSoyd4.js} +2 -2
  158. package/dist/components/{p-BHjw0x3L.js.map → p-DAqSoyd4.js.map} +1 -1
  159. package/dist/components/p-DEjh3klB.js +2 -0
  160. package/dist/components/{p-CKJzHclc.js.map → p-DEjh3klB.js.map} +1 -1
  161. package/dist/components/{p-NdahPypA.js → p-DFQ9mcbK.js} +2 -2
  162. package/dist/components/{p-Ck_VRQYi.js → p-DHuyj-9J.js} +2 -2
  163. package/dist/components/{p-Ck_VRQYi.js.map → p-DHuyj-9J.js.map} +1 -1
  164. package/dist/components/p-DIEK54fV.js +2 -0
  165. package/dist/components/{p-URdgCwEs.js.map → p-DIEK54fV.js.map} +1 -1
  166. package/dist/components/{p-Bf_D3crn.js → p-DNJTN_s0.js} +2 -2
  167. package/dist/components/p-DOqnJVos.js +2 -0
  168. package/dist/components/{p-CWDmHPJC.js.map → p-DOqnJVos.js.map} +1 -1
  169. package/dist/components/{p-DL_5VENG.js → p-DQqOzDEq.js} +2 -2
  170. package/dist/components/{p-D-kWb8cF.js → p-DSIOINBK.js} +2 -2
  171. package/dist/components/{p-C5eosu67.js → p-DZ55e3j9.js} +2 -2
  172. package/dist/components/{p-C5eosu67.js.map → p-DZ55e3j9.js.map} +1 -1
  173. package/dist/components/{p-QdI17bl-.js → p-Dg9qiMDa.js} +2 -2
  174. package/dist/components/p-DsJW5W3W.js +2 -0
  175. package/dist/components/{p-C2n8A8NA.js.map → p-DsJW5W3W.js.map} +1 -1
  176. package/dist/components/p-JPTkZ3Ji.js +2 -0
  177. package/dist/components/p-JPTkZ3Ji.js.map +1 -0
  178. package/dist/components/p-NzGRAPcF.js +2 -0
  179. package/dist/components/p-NzGRAPcF.js.map +1 -0
  180. package/dist/components/{p-B7Hf86NF.js → p-PD1Vfg0t.js} +2 -2
  181. package/dist/components/{p-B7Hf86NF.js.map → p-PD1Vfg0t.js.map} +1 -1
  182. package/dist/components/{p-BxqBiVbH.js → p-U8JIZzI2.js} +2 -2
  183. package/dist/components/{p-BxqBiVbH.js.map → p-U8JIZzI2.js.map} +1 -1
  184. package/dist/components/{p-CKY989vF.js → p-ZZzC52Ea.js} +2 -2
  185. package/dist/components/{p-CKY989vF.js.map → p-ZZzC52Ea.js.map} +1 -1
  186. package/dist/components/p-__lNIImO.js +2 -0
  187. package/dist/components/{p-CnWC0QvG.js.map → p-__lNIImO.js.map} +1 -1
  188. package/dist/components/{p-vWK5faWZ.js → p-a6qP60zb.js} +2 -2
  189. package/dist/components/{p-CjgnFGd6.js → p-rrFMAZkj.js} +2 -2
  190. package/dist/components/{p-CjgnFGd6.js.map → p-rrFMAZkj.js.map} +1 -1
  191. package/dist/components/p-ruPTIV6t.js +2 -0
  192. package/dist/components/{p-M9DPfXbP.js.map → p-ruPTIV6t.js.map} +1 -1
  193. package/dist/components/{p-jMCRaxQW.js → p-y4jhIkRc.js} +2 -2
  194. package/dist/components/{p-jMCRaxQW.js.map → p-y4jhIkRc.js.map} +1 -1
  195. package/dist/docs/components.json +813 -76
  196. package/dist/mcp-data/registry/button-unfilled.json +26 -7
  197. package/dist/mcp-data/registry/filter-menu.json +21 -2
  198. package/dist/mcp-data/registry/loader.json +2 -1
  199. package/dist/mcp-data/registry/registry.json +322 -23
  200. package/dist/mcp-data/registry/select.json +22 -3
  201. package/dist/mcp-data/registry/table-filter.json +399 -0
  202. package/dist/mcp-data/registry/table-saved-views.json +4 -4
  203. package/dist/mcp-data/registry/table-sort.json +229 -0
  204. package/dist/mcp-data/registry/table-toolbar.json +21 -14
  205. package/dist/mcp-data/registry/table.json +11 -8
  206. package/dist/react/components.d.ts +2 -0
  207. package/dist/react/components.js +2 -0
  208. package/dist/react/ds-table-filter.d.ts +17 -0
  209. package/dist/react/ds-table-filter.js +19 -0
  210. package/dist/react/ds-table-sort.d.ts +12 -0
  211. package/dist/react/ds-table-sort.js +12 -0
  212. package/dist/types/components/ButtonUnfilled/ButtonUnfilled.d.ts +18 -1
  213. package/dist/types/components/FilterMenu/FilterMenu.d.ts +13 -0
  214. package/dist/types/components/Select/Select.d.ts +13 -0
  215. package/dist/types/components/Table/Table.d.ts +4 -0
  216. package/dist/types/components/Table/table-column-customizer.d.ts +2 -0
  217. package/dist/types/components/TableFilter/TableFilter.d.ts +37 -0
  218. package/dist/types/components/TableSort/TableSort.d.ts +24 -0
  219. package/dist/types/components/TableSort/table-sort-menu.d.ts +15 -0
  220. package/dist/types/components.d.ts +254 -2
  221. package/dist/types/utils/table-caption-compact.d.ts +6 -0
  222. package/dist/vue/components.d.ts +2 -0
  223. package/dist/vue/components.js +2 -0
  224. package/dist/vue/ds-button-unfilled.js +1 -0
  225. package/dist/vue/ds-filter-menu.js +1 -0
  226. package/dist/vue/ds-select.js +1 -0
  227. package/dist/vue/ds-table-filter.d.ts +3 -0
  228. package/dist/vue/ds-table-filter.js +29 -0
  229. package/dist/vue/ds-table-sort.d.ts +3 -0
  230. package/dist/vue/ds-table-sort.js +13 -0
  231. package/package.json +1 -1
  232. package/dist/components/p-BzLnSwG9.js +0 -2
  233. package/dist/components/p-C2n8A8NA.js +0 -2
  234. package/dist/components/p-C7rzVotG.js +0 -2
  235. package/dist/components/p-C7rzVotG.js.map +0 -1
  236. package/dist/components/p-CKJzHclc.js +0 -2
  237. package/dist/components/p-CWDmHPJC.js +0 -2
  238. package/dist/components/p-Ca-I2UnB.js +0 -2
  239. package/dist/components/p-Ca-I2UnB.js.map +0 -1
  240. package/dist/components/p-CnWC0QvG.js +0 -2
  241. package/dist/components/p-CooNucm0.js +0 -2
  242. package/dist/components/p-CooNucm0.js.map +0 -1
  243. package/dist/components/p-DLkNcCY0.js +0 -2
  244. package/dist/components/p-M9DPfXbP.js +0 -2
  245. package/dist/components/p-URdgCwEs.js +0 -2
  246. /package/dist/components/{p-C1q-tq3U.js.map → p-7tZx4ukz.js.map} +0 -0
  247. /package/dist/components/{p-DZFilC--.js.map → p-BGXqFq2C.js.map} +0 -0
  248. /package/dist/components/{p-Dcnd5ZX5.js.map → p-BKp__CQX.js.map} +0 -0
  249. /package/dist/components/{p-B80NfEqc.js.map → p-C0X2zKbB.js.map} +0 -0
  250. /package/dist/components/{p-Ct-m0I6U.js.map → p-C4TgWJi9.js.map} +0 -0
  251. /package/dist/components/{p-DTMxwYQj.js.map → p-CMFvaY05.js.map} +0 -0
  252. /package/dist/components/{p-BagXfn1G.js.map → p-D1YhYulL.js.map} +0 -0
  253. /package/dist/components/{p-BXPQmp7q.js.map → p-D4K9CE8a.js.map} +0 -0
  254. /package/dist/components/{p-NdahPypA.js.map → p-DFQ9mcbK.js.map} +0 -0
  255. /package/dist/components/{p-Bf_D3crn.js.map → p-DNJTN_s0.js.map} +0 -0
  256. /package/dist/components/{p-DL_5VENG.js.map → p-DQqOzDEq.js.map} +0 -0
  257. /package/dist/components/{p-D-kWb8cF.js.map → p-DSIOINBK.js.map} +0 -0
  258. /package/dist/components/{p-QdI17bl-.js.map → p-Dg9qiMDa.js.map} +0 -0
  259. /package/dist/components/{p-vWK5faWZ.js.map → p-a6qP60zb.js.map} +0 -0
@@ -0,0 +1,229 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "table-sort",
4
+ "title": "TableSort",
5
+ "description": "Toolbar companion for the table's one controlled member-row sort, with a two-section menu for the sort field and direction that mirrors header sorting.",
6
+ "type": "registry:ui",
7
+ "meta": {
8
+ "library": "@ds-mo/ui",
9
+ "distribution": "npm",
10
+ "storybook": "https://zainadeel.github.io/compomo/?path=/story/table-sort",
11
+ "source": "src/wc/components/TableSort/TableSort.tsx",
12
+ "intentStatus": "complete",
13
+ "intent": {
14
+ "audience": "general",
15
+ "status": "stable",
16
+ "summary": "Toolbar companion for the table's one controlled member-row sort, with a two-section menu for the sort field and direction that mirrors header sorting.",
17
+ "useWhen": [
18
+ "A table toolbar needs an explicit Sort control alongside Filter and Group.",
19
+ "Sortable columns or compound header segments should be choosable without relying only on column-header clicks."
20
+ ],
21
+ "avoidWhen": [
22
+ "The table has no sortable columns; the control hides itself.",
23
+ "The application expects the control to sort rows internally or persist preferences.",
24
+ "The popup should submit a form value; use Select."
25
+ ],
26
+ "alternatives": [
27
+ {
28
+ "when": "The choice is one submitted form value.",
29
+ "component": "component:ds-select",
30
+ "reason": "Select owns form-value and listbox semantics, not table sort state."
31
+ }
32
+ ],
33
+ "commonlyComposedWith": [
34
+ "component:ds-table",
35
+ "component:ds-table-toolbar",
36
+ "component:ds-table-filter",
37
+ "component:ds-select",
38
+ "component:ds-button-unfilled",
39
+ "component:ds-menu"
40
+ ],
41
+ "patterns": [
42
+ "pattern:menu-trigger"
43
+ ],
44
+ "accessibility": [
45
+ "The trigger is an icon-label menu button named Sort table unless a product aria-label is supplied. Compact caption widths keep that accessible name after the visible label is omitted.",
46
+ "The menu has two sections, Data and Direction. Each section presents one selected row through isSelected; the menu is not a single radio group because field and direction are independent.",
47
+ "Choosing a row applies immediately and keeps the menu open so the other section can be changed. Escape and outside activation close the menu and restore trigger focus."
48
+ ],
49
+ "states": [
50
+ "columns and sort are controlled. dsSortChange reports the next TableSortState and never mutates those inputs. The same sort object is what column headers emit through the table.",
51
+ "Selecting a different data field keeps the current direction, or starts ascending when no sort exists. Selecting a direction applies it to the current field, or to the first sortable field when no sort exists. Selecting the already-active field or direction is a no-op and does not toggle the way a header click does.",
52
+ "The trigger stays Sort in resting secondary chrome. Field and direction selection live in the menu and on column headers, so the trigger never uses active primary emphasis.",
53
+ "Compound sortable headers contribute one Data row per segment. Action columns never appear."
54
+ ],
55
+ "responsiveBehavior": [
56
+ "Place the control in the trailing region of ds-table-toolbar with Filter and Group.",
57
+ "Inside a named ds-table container narrower than 900px, the trigger omits its label and chevron and becomes icon-only. The icon keeps the resting secondary foreground."
58
+ ],
59
+ "frameworkCaveats": {
60
+ "customElements": [
61
+ "Assign columns and sort as JavaScript properties. Replace sort from both dsSortChange on this control and dsSortChange on the table."
62
+ ],
63
+ "react": [
64
+ "Keep one sort state and pass it to both ds-table and ds-table-sort; update it from either event."
65
+ ],
66
+ "angular": [
67
+ "Import the generated DsTableSort adapter, bind columns and sort, and handle dsSortChange with the same owner that handles table header sorting."
68
+ ]
69
+ },
70
+ "references": [
71
+ {
72
+ "label": "Storybook review states",
73
+ "path": "src/wc/components/TableSort/TableSort.stories.ts"
74
+ },
75
+ {
76
+ "label": "Toolbar composition owner",
77
+ "path": "src/wc/components/TableToolbar/TableToolbar.agent.json"
78
+ }
79
+ ]
80
+ },
81
+ "api": {
82
+ "props": {
83
+ "ariaLabel": {
84
+ "type": "string | null",
85
+ "resolvedType": "null | string",
86
+ "attribute": "aria-label",
87
+ "default": "null",
88
+ "required": false,
89
+ "mutable": false,
90
+ "description": "Accessible name for the trigger and menu."
91
+ },
92
+ "columns": {
93
+ "type": "TableColumn[]",
94
+ "resolvedType": "TableColumn[]",
95
+ "default": "[]",
96
+ "required": false,
97
+ "mutable": false,
98
+ "description": "Catalog used to derive sortable fields, including compound header segments."
99
+ },
100
+ "sort": {
101
+ "type": "TableSortState | null",
102
+ "resolvedType": "TableSortState | null",
103
+ "default": "null",
104
+ "required": false,
105
+ "mutable": false,
106
+ "description": "Controlled table sort. Header sorting and this menu share the same value."
107
+ }
108
+ },
109
+ "events": [
110
+ {
111
+ "name": "dsSortChange",
112
+ "detail": "TableSortChangeDetail",
113
+ "bubbles": false,
114
+ "cancelable": true,
115
+ "composed": true
116
+ }
117
+ ],
118
+ "methods": [
119
+ {
120
+ "name": "setFocus",
121
+ "signature": "setFocus() => Promise<void>"
122
+ }
123
+ ],
124
+ "slots": []
125
+ },
126
+ "props": {
127
+ "ariaLabel": {
128
+ "type": "string | null",
129
+ "resolvedType": "null | string",
130
+ "attribute": "aria-label",
131
+ "default": "null",
132
+ "required": false,
133
+ "mutable": false,
134
+ "description": "Accessible name for the trigger and menu."
135
+ },
136
+ "columns": {
137
+ "type": "TableColumn[]",
138
+ "resolvedType": "TableColumn[]",
139
+ "default": "[]",
140
+ "required": false,
141
+ "mutable": false,
142
+ "description": "Catalog used to derive sortable fields, including compound header segments."
143
+ },
144
+ "sort": {
145
+ "type": "TableSortState | null",
146
+ "resolvedType": "TableSortState | null",
147
+ "default": "null",
148
+ "required": false,
149
+ "mutable": false,
150
+ "description": "Controlled table sort. Header sorting and this menu share the same value."
151
+ }
152
+ },
153
+ "events": [
154
+ {
155
+ "name": "dsSortChange",
156
+ "detail": "TableSortChangeDetail",
157
+ "bubbles": false,
158
+ "cancelable": true,
159
+ "composed": true
160
+ }
161
+ ],
162
+ "methods": [
163
+ {
164
+ "name": "setFocus",
165
+ "signature": "setFocus() => Promise<void>"
166
+ }
167
+ ],
168
+ "slots": [],
169
+ "exports": {
170
+ "customElement": "ds-table-sort",
171
+ "react": "DsTableSort",
172
+ "vue": "DsTableSort",
173
+ "angular": "DsTableSort"
174
+ },
175
+ "consumption": {
176
+ "install": "npm install @ds-mo/ui @ds-mo/tokens @ds-mo/icons",
177
+ "cssSetup": "import '@ds-mo/tokens';\nimport '@ds-mo/tokens/reset';\nimport '@ds-mo/tokens/globals';",
178
+ "customElements": {
179
+ "import": "import '@ds-mo/ui/dist/components/ds-table-sort.js';",
180
+ "example": "<ds-table-sort></ds-table-sort>"
181
+ },
182
+ "react": {
183
+ "import": "import { DsTableSort } from '@ds-mo/ui/react';",
184
+ "example": "<DsTableSort />"
185
+ },
186
+ "vue": {
187
+ "import": "import { DsTableSort } from '@ds-mo/ui/vue';",
188
+ "example": "<DsTableSort />"
189
+ },
190
+ "angular": {
191
+ "import": "import { DsTableSort } from '@ds-mo/ui/angular/ds-table-sort';",
192
+ "example": "<ds-table-sort></ds-table-sort>"
193
+ },
194
+ "complexPropertyNote": "Assign these non-primitive values as JavaScript properties: columns, sort.",
195
+ "peerDependencies": {
196
+ "required": [
197
+ "@ds-mo/tokens ^6.5.0",
198
+ "@ds-mo/icons ^7.0.0"
199
+ ],
200
+ "frameworks": "Custom Elements; React 18/19 wrappers; Vue 3 wrappers; Angular 19-22 standalone adapters."
201
+ }
202
+ }
203
+ },
204
+ "dependencies": [
205
+ "@ds-mo/ui",
206
+ "@ds-mo/tokens"
207
+ ],
208
+ "registryDependencies": [
209
+ "button-unfilled",
210
+ "menu"
211
+ ],
212
+ "files": [
213
+ {
214
+ "path": "src/wc/components/TableSort/TableSort.css",
215
+ "content": ":host {\n display: inline-flex;\n min-inline-size: 0;\n max-inline-size: var(--dimension-menu-width-xs);\n}\n\n:host([hidden]) {\n display: none;\n}\n",
216
+ "type": "registry:ui"
217
+ },
218
+ {
219
+ "path": "src/wc/components/TableSort/TableSort.tsx",
220
+ "content": "import { Component, Element, Event, EventEmitter, h, Host, Method, Prop, State } from '@stencil/core';\nimport type { MenuItemData } from '../Menu/menu-types';\nimport type { TableColumn, TableSortChangeDetail, TableSortState } from '../Table/table-types';\nimport {\n nextTableSortStateFromMenuItem,\n tableSortFields,\n tableSortMenuSections,\n tableSortStatesEqual,\n} from './table-sort-menu';\n\nlet tableSortSeq = 0;\n\n@Component({\n tag: 'ds-table-sort',\n styleUrl: 'TableSort.css',\n scoped: true,\n})\nexport class TableSort {\n @Element() private el!: HTMLElement;\n\n /** Catalog used to derive sortable fields, including compound header segments. */\n @Prop() columns: TableColumn[] = [];\n /** Controlled table sort. Header sorting and this menu share the same value. */\n @Prop() sort: TableSortState | null = null;\n /** Accessible name for the trigger and menu. */\n @Prop({ attribute: 'aria-label' }) ariaLabel: string | null = null;\n\n @Event({ bubbles: false }) dsSortChange!: EventEmitter<TableSortChangeDetail>;\n\n @State() private menuOpen = false;\n @State() private initialFocusVisible = false;\n\n private readonly componentId = `ds-table-sort-${++tableSortSeq}`;\n private readonly triggerId = `${this.componentId}-trigger`;\n private readonly menuId = `${this.componentId}-menu`;\n\n @Method()\n async setFocus() {\n const trigger = this.el.querySelector<HTMLElement & { setFocus?: () => Promise<void> }>(\n `#${CSS.escape(this.triggerId)}`\n );\n await trigger?.setFocus?.();\n }\n\n render() {\n const fields = tableSortFields(this.columns);\n const name = this.ariaLabel?.trim() || 'Sort table';\n\n return (\n <Host hidden={fields.length === 0 ? true : undefined}>\n {fields.length === 0 ? null : (\n <ds-button-unfilled\n id={this.triggerId}\n variant=\"icon-label\"\n size=\"md\"\n icon=\"ArrowsVertical\"\n label=\"Sort\"\n aria-label={name}\n hasMenu={true}\n collapseLabel={true}\n expanded={this.menuOpen}\n controls={this.menuId}\n onDsClick={(event: CustomEvent<MouseEvent>) => {\n this.toggle(event.detail.detail === 0);\n }}\n />\n )}\n {fields.length === 0 ? null : (\n <ds-menu\n id={this.menuId}\n open={this.menuOpen}\n anchorId={this.triggerId}\n align=\"end\"\n side=\"bottom\"\n menuLabel={name}\n selectionMode=\"none\"\n initialFocusVisible={this.initialFocusVisible}\n sections={tableSortMenuSections(this.columns, this.sort)}\n onDsClose={() => this.close()}\n onDsSelect={event => this.handleSelect(event.detail)}\n />\n )}\n </Host>\n );\n }\n\n private toggle(fromKeyboard = false): void {\n if (this.menuOpen) this.close();\n else this.open(fromKeyboard);\n }\n\n private open(fromKeyboard = false): void {\n if (this.menuOpen) return;\n this.initialFocusVisible = fromKeyboard;\n this.menuOpen = true;\n }\n\n private close(): void {\n this.menuOpen = false;\n }\n\n private handleSelect(item: MenuItemData): void {\n const next = nextTableSortStateFromMenuItem(this.columns, this.sort, item);\n if (tableSortStatesEqual(this.sort, next)) return;\n this.dsSortChange.emit({ sort: next });\n }\n}\n",
221
+ "type": "registry:ui"
222
+ },
223
+ {
224
+ "path": "src/wc/components/TableSort/table-sort-menu.ts",
225
+ "content": "import type { MenuItemData, MenuSection } from '../Menu/menu-types';\nimport { isTableActionColumn } from '../Table/table-column-customizer';\nimport type { TableColumn, TableSortState } from '../Table/table-types';\n\nexport const TABLE_SORT_DIRECTION_ASC = 'direction:asc';\nexport const TABLE_SORT_DIRECTION_DESC = 'direction:desc';\nconst TABLE_SORT_FIELD_PREFIX = 'field:';\n\nexport interface TableSortField {\n id: string;\n label: string;\n}\n\n/** Sortable data fields from the catalog, including compound header segments. */\nexport function tableSortFields(columns: readonly TableColumn[]): TableSortField[] {\n const fields: TableSortField[] = [];\n const seen = new Set<string>();\n\n for (const column of columns) {\n if (isTableActionColumn(column) || !column.sortable) continue;\n const segments = column.headerSegments?.filter(segment => segment.sortKey.trim()) ?? [];\n if (segments.length > 0) {\n for (const segment of segments) {\n if (seen.has(segment.sortKey)) continue;\n seen.add(segment.sortKey);\n fields.push({\n id: segment.sortKey,\n label: segment.label.trim() || segment.sortKey,\n });\n }\n continue;\n }\n if (seen.has(column.id)) continue;\n seen.add(column.id);\n fields.push({\n id: column.id,\n label: column.header.trim() || column.headerLabel?.trim() || column.id,\n });\n }\n\n return fields;\n}\n\nexport function tableSortMenuSections(\n columns: readonly TableColumn[],\n sort: TableSortState | null | undefined\n): MenuSection[] {\n const fields = tableSortFields(columns);\n return [\n {\n header: 'Data',\n items: fields.map(field => ({\n label: field.label,\n value: `${TABLE_SORT_FIELD_PREFIX}${encodeURIComponent(field.id)}`,\n isSelected: sort?.columnId === field.id,\n })),\n },\n {\n header: 'Direction',\n items: [\n {\n label: 'Ascending',\n value: TABLE_SORT_DIRECTION_ASC,\n icon: 'ArrowUp',\n isSelected: sort?.direction === 'asc',\n },\n {\n label: 'Descending',\n value: TABLE_SORT_DIRECTION_DESC,\n icon: 'ArrowDown',\n isSelected: sort?.direction === 'desc',\n },\n ],\n },\n ];\n}\n\nexport function tableSortStatesEqual(\n left: TableSortState | null | undefined,\n right: TableSortState | null | undefined\n): boolean {\n if (left === right) return true;\n if (!left || !right) return false;\n return left.columnId === right.columnId && left.direction === right.direction;\n}\n\n/** Next controlled sort from a Sort menu selection. Does not toggle like a header click. */\nexport function nextTableSortStateFromMenuItem(\n columns: readonly TableColumn[],\n current: TableSortState | null | undefined,\n item: MenuItemData\n): TableSortState | null {\n const fields = tableSortFields(columns);\n if (fields.length === 0) return current ?? null;\n\n if (item.value === TABLE_SORT_DIRECTION_ASC || item.value === TABLE_SORT_DIRECTION_DESC) {\n const direction = item.value === TABLE_SORT_DIRECTION_ASC ? 'asc' : 'desc';\n const columnId = fields.some(field => field.id === current?.columnId)\n ? current!.columnId\n : fields[0]!.id;\n return { columnId, direction };\n }\n\n if (!item.value?.startsWith(TABLE_SORT_FIELD_PREFIX)) return current ?? null;\n let columnId: string;\n try {\n columnId = decodeURIComponent(item.value.slice(TABLE_SORT_FIELD_PREFIX.length));\n } catch {\n return current ?? null;\n }\n if (!fields.some(field => field.id === columnId)) return current ?? null;\n if (current?.columnId === columnId) return current ?? null;\n return { columnId, direction: current?.direction ?? 'asc' };\n}\n",
226
+ "type": "registry:ui"
227
+ }
228
+ ]
229
+ }
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
3
  "name": "table-toolbar",
4
4
  "title": "TableToolbar",
5
- "description": "Data-agnostic companion layout for application-owned controls in a table header, with leading and trailing control groups and narrow-width horizontal overflow.",
5
+ "description": "Data-agnostic companion layout for application-owned table caption controls, with a start cluster, optional search, trailing Filter/Group/Sort, and narrow-width horizontal overflow.",
6
6
  "type": "registry:ui",
7
7
  "meta": {
8
8
  "library": "@ds-mo/ui",
@@ -13,9 +13,9 @@
13
13
  "intent": {
14
14
  "audience": "general",
15
15
  "status": "stable",
16
- "summary": "Data-agnostic companion layout for application-owned controls in a table header, with leading and trailing control groups and narrow-width horizontal overflow.",
16
+ "summary": "Data-agnostic companion layout for application-owned table caption controls, with a start cluster, optional search, trailing Filter/Group/Sort, and narrow-width horizontal overflow.",
17
17
  "useWhen": [
18
- "Several table pages repeat the same leading discovery controls and trailing result-shaping controls.",
18
+ "Several table pages repeat the same saved-view cluster, middle discovery and result-shaping controls, and table-owned caption actions.",
19
19
  "A ds-table header slot needs consistent control spacing, alignment, grouping, and narrow-width overflow without moving product behavior into the table."
20
20
  ],
21
21
  "avoidWhen": [
@@ -26,34 +26,39 @@
26
26
  "commonlyComposedWith": [
27
27
  "component:ds-table",
28
28
  "component:ds-table-saved-views",
29
+ "component:ds-divider",
29
30
  "component:ds-input",
30
- "component:ds-filter-menu",
31
+ "component:ds-table-filter",
32
+ "component:ds-select",
33
+ "component:ds-table-sort",
31
34
  "component:ds-button-unfilled"
32
35
  ],
33
36
  "patterns": [],
34
37
  "accessibility": [
35
38
  "The component exposes a named toolbar while each slotted control retains its own accessible name and native keyboard behavior.",
36
- "Use the leading slot for discovery and context controls such as saved views and search. Use the trailing slot for result-shaping controls such as filters and grouping.",
39
+ "Use the start slot for saved views. Use search for the optional discovery field, leading for any additional left-side middle controls, and trailing for Filter, Group, and Sort. Table-owned column customizer and data-mode actions remain in the table caption trailing cluster.",
37
40
  "Tab order follows authored DOM order. The toolbar does not add roving focus because it may contain heterogeneous form and popup controls."
38
41
  ],
39
42
  "states": [
40
- "The component owns layout only. Slotted controls, values, menus, loading, persistence, and consequences remain controlled by the application. Use ds-table-saved-views when saved-view interaction needs the shared CompoMo behavior while application storage remains external.",
41
- "Either region may be empty. The populated region continues to occupy the available width without adding placeholder chrome."
43
+ "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.",
44
+ "The start cluster is followed by a decorative vertical divider, then the spanning middle region. 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. The middle region occupies remaining width so trailing controls stay at its inline end.",
45
+ "Column customizer and data-mode switching stay table-owned caption actions. Do not recreate those menus in the toolbar."
42
46
  ],
43
47
  "responsiveBehavior": [
44
- "The two control groups stay on one line and horizontally scroll when their complete controls no longer fit.",
48
+ "The start cluster, search, trailing Filter/Group/Sort, 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, Group, and Sort triggers cap at the same token, and Group and Sort popups keep that compact menu-width floor. The toolbar horizontally scrolls when its complete controls no longer fit.",
49
+ "Inside a named ds-table container narrower than 900px, ds-table-filter and ds-table-sort omit their labels and chevrons and become icon-only. Group controls explicitly opt into the same treatment with collapseLabel. 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.",
45
50
  "The scrollbar is visually suppressed without removing touch, trackpad, mouse-wheel, or keyboard scrolling from the overflow container.",
46
51
  "Trailing controls remain grouped after leading controls; the toolbar does not collapse controls into an application-specific overflow menu."
47
52
  ],
48
53
  "frameworkCaveats": {
49
54
  "customElements": [
50
- "Project controls through slot=leading or slot=trailing and provide a label that names their table context when Table controls is insufficient."
55
+ "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."
51
56
  ],
52
57
  "react": [
53
- "Set slot=leading or slot=trailing on each child control; keep values and event handlers in the application."
58
+ "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."
54
59
  ],
55
60
  "angular": [
56
- "Set slot=leading or slot=trailing on each child control and import the generated DsTableToolbar adapter alongside those controls."
61
+ "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."
57
62
  ]
58
63
  },
59
64
  "references": [
@@ -135,16 +140,18 @@
135
140
  "@ds-mo/ui",
136
141
  "@ds-mo/tokens"
137
142
  ],
138
- "registryDependencies": [],
143
+ "registryDependencies": [
144
+ "divider"
145
+ ],
139
146
  "files": [
140
147
  {
141
148
  "path": "src/wc/components/TableToolbar/TableToolbar.css",
142
- "content": ":host {\n display: block;\n min-inline-size: 0;\n max-inline-size: 100%;\n}\n\n.table-toolbar {\n box-sizing: border-box;\n display: flex;\n align-items: center;\n inline-size: 100%;\n min-inline-size: 0;\n gap: var(--dimension-space-100);\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: none;\n}\n\n.table-toolbar::-webkit-scrollbar {\n display: none;\n}\n\n.table-toolbar__leading,\n.table-toolbar__trailing {\n display: flex;\n align-items: center;\n min-inline-size: 0;\n gap: var(--dimension-space-100);\n}\n\n.table-toolbar__leading {\n flex: 1 0 auto;\n}\n\n.table-toolbar__trailing {\n flex: 0 0 auto;\n margin-inline-start: auto;\n}\n\n.table-toolbar__leading slot,\n.table-toolbar__trailing slot {\n display: contents;\n}\n",
149
+ "content": ":host {\n display: block;\n min-inline-size: 0;\n max-inline-size: 100%;\n}\n\n.table-toolbar {\n box-sizing: border-box;\n display: flex;\n align-items: center;\n inline-size: 100%;\n min-inline-size: 0;\n gap: var(--dimension-space-100);\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: none;\n}\n\n.table-toolbar::-webkit-scrollbar {\n display: none;\n}\n\n.table-toolbar__start,\n.table-toolbar__search,\n.table-toolbar__main,\n.table-toolbar__leading,\n.table-toolbar__trailing {\n display: flex;\n align-items: center;\n min-inline-size: 0;\n gap: var(--dimension-space-100);\n}\n\n.table-toolbar__start {\n flex: 0 0 auto;\n min-inline-size: 0;\n max-inline-size: var(--dimension-menu-width-xs);\n overflow: hidden;\n}\n\n.table-toolbar__rule {\n flex: 0 0 auto;\n}\n\n.table-toolbar__main {\n flex: 1 1 auto;\n min-inline-size: min-content;\n}\n\n.table-toolbar__search {\n flex: 0 1 var(--dimension-panel-width-xs);\n max-inline-size: var(--dimension-panel-width-xs);\n}\n\n:host(:not(:has([slot='search']))) .table-toolbar__search {\n display: none;\n}\n\n:host(:not(:has([slot='start']))) .table-toolbar__start,\n:host(:not(:has([slot='start']))) .table-toolbar__rule {\n display: none;\n}\n\n.table-toolbar__leading {\n flex: 1 0 auto;\n}\n\n.table-toolbar__trailing {\n flex: 0 0 auto;\n margin-inline-start: auto;\n}\n\n.table-toolbar__trailing > *,\n.table-toolbar [slot='start'],\n.table-toolbar ds-table-filter,\n.table-toolbar ds-filter-menu,\n.table-toolbar ds-select,\n.table-toolbar ds-table-sort {\n min-inline-size: 0;\n max-inline-size: var(--dimension-menu-width-xs);\n --ds-choice-popup-min-inline-size: var(--dimension-menu-width-xs);\n}\n\n.table-toolbar__start slot,\n.table-toolbar__search slot,\n.table-toolbar__leading slot,\n.table-toolbar__trailing slot {\n display: contents;\n}\n",
143
150
  "type": "registry:ui"
144
151
  },
145
152
  {
146
153
  "path": "src/wc/components/TableToolbar/TableToolbar.tsx",
147
- "content": "import { Component, h, Host, Prop } from '@stencil/core';\n\n@Component({\n tag: 'ds-table-toolbar',\n styleUrl: 'TableToolbar.css',\n scoped: true,\n})\nexport class TableToolbar {\n /** Accessible name for the grouped table controls. */\n @Prop() label: string = 'Table controls';\n\n render() {\n return (\n <Host>\n <div class=\"table-toolbar\" role=\"toolbar\" aria-label={this.label}>\n <div class=\"table-toolbar__leading\">\n <slot name=\"leading\" />\n </div>\n <div class=\"table-toolbar__trailing\">\n <slot name=\"trailing\" />\n </div>\n </div>\n </Host>\n );\n }\n}\n",
154
+ "content": "import { Component, h, Host, Prop } from '@stencil/core';\n\n@Component({\n tag: 'ds-table-toolbar',\n styleUrl: 'TableToolbar.css',\n scoped: true,\n})\nexport class TableToolbar {\n /** Accessible name for the grouped table controls. */\n @Prop() label: string = 'Table controls';\n\n render() {\n return (\n <Host>\n <div class=\"table-toolbar\" role=\"toolbar\" aria-label={this.label}>\n <div class=\"table-toolbar__start\">\n <slot name=\"start\" />\n </div>\n <ds-divider class=\"table-toolbar__rule\" orientation=\"vertical\" length=\"32px\" />\n <div class=\"table-toolbar__main\">\n <div class=\"table-toolbar__search\">\n <slot name=\"search\" />\n </div>\n <div class=\"table-toolbar__leading\">\n <slot name=\"leading\" />\n </div>\n <div class=\"table-toolbar__trailing\">\n <slot name=\"trailing\" />\n </div>\n </div>\n </div>\n </Host>\n );\n }\n}\n",
148
155
  "type": "registry:ui"
149
156
  }
150
157
  ]