@xmesh/system-design 0.0.4 → 0.0.6

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 (290) hide show
  1. package/README.md +2 -1
  2. package/custom-elements.json +18382 -0
  3. package/dist/lit/components/alert/index.d.ts +5 -0
  4. package/dist/lit/components/alert/index.js +8 -2
  5. package/dist/lit/components/alert/index.styles.js +215 -0
  6. package/dist/lit/components/app-bar/index.d.ts +1 -0
  7. package/dist/lit/components/app-bar/index.js +4 -2
  8. package/dist/lit/components/app-bar/index.styles.js +94 -0
  9. package/dist/lit/components/artifact/index.d.ts +5 -0
  10. package/dist/lit/components/artifact/index.js +14 -10
  11. package/dist/lit/components/artifact/index.styles.js +180 -0
  12. package/dist/lit/components/autocomplete/index.d.ts +5 -0
  13. package/dist/lit/components/autocomplete/index.js +11 -2
  14. package/dist/lit/components/autocomplete/index.styles.js +185 -0
  15. package/dist/lit/components/avatar/index.d.ts +1 -0
  16. package/dist/lit/components/avatar/index.js +4 -2
  17. package/dist/lit/components/avatar/index.styles.js +76 -0
  18. package/dist/lit/components/avatar-group/index.d.ts +1 -0
  19. package/dist/lit/components/avatar-group/index.js +4 -2
  20. package/dist/lit/components/avatar-group/index.styles.js +74 -0
  21. package/dist/lit/components/badge/index.d.ts +1 -0
  22. package/dist/lit/components/badge/index.js +4 -2
  23. package/dist/lit/components/badge/index.styles.js +86 -0
  24. package/dist/lit/components/brand-mark/index.js +8 -9
  25. package/dist/lit/components/brand-mark/index.styles.js +123 -0
  26. package/dist/lit/components/breadcrumbs/index.d.ts +1 -0
  27. package/dist/lit/components/breadcrumbs/index.js +5 -4
  28. package/dist/lit/components/breadcrumbs/index.styles.js +105 -0
  29. package/dist/lit/components/bubble/index.d.ts +4 -0
  30. package/dist/lit/components/bubble/index.js +14 -11
  31. package/dist/lit/components/bubble/index.styles.js +196 -0
  32. package/dist/lit/components/button/index.d.ts +1 -0
  33. package/dist/lit/components/button/index.js +6 -13
  34. package/dist/lit/components/button/index.styles.js +356 -0
  35. package/dist/lit/components/card/index.d.ts +1 -0
  36. package/dist/lit/components/card/index.js +4 -2
  37. package/dist/lit/components/card/index.styles.js +113 -0
  38. package/dist/lit/components/chat/index.d.ts +6 -0
  39. package/dist/lit/components/chat/index.js +15 -10
  40. package/dist/lit/components/chat/index.styles.js +306 -0
  41. package/dist/lit/components/checkbox/index.d.ts +1 -0
  42. package/dist/lit/components/checkbox/index.js +7 -4
  43. package/dist/lit/components/checkbox/index.styles.js +140 -0
  44. package/dist/lit/components/chip/index.d.ts +5 -0
  45. package/dist/lit/components/chip/index.js +8 -2
  46. package/dist/lit/components/chip/index.styles.js +159 -0
  47. package/dist/lit/components/chip-group/index.d.ts +4 -0
  48. package/dist/lit/components/chip-group/index.js +7 -2
  49. package/dist/lit/components/chip-group/index.styles.js +33 -0
  50. package/dist/lit/components/code/index.d.ts +1 -0
  51. package/dist/lit/components/code/index.js +4 -3
  52. package/dist/lit/components/code/index.styles.js +56 -0
  53. package/dist/lit/components/composer/index.d.ts +6 -0
  54. package/dist/lit/components/composer/index.js +15 -10
  55. package/dist/lit/components/composer/index.styles.js +562 -0
  56. package/dist/lit/components/data-table/index.css +18 -0
  57. package/dist/lit/components/data-table/index.d.ts +30 -0
  58. package/dist/lit/components/data-table/index.js +120 -34
  59. package/dist/lit/components/data-table/index.styles.js +198 -0
  60. package/dist/lit/components/date-range/index.d.ts +4 -0
  61. package/dist/lit/components/date-range/index.js +7 -2
  62. package/dist/lit/components/date-range/index.styles.js +338 -0
  63. package/dist/lit/components/dialog/index.d.ts +4 -0
  64. package/dist/lit/components/dialog/index.js +7 -2
  65. package/dist/lit/components/dialog/index.styles.js +138 -0
  66. package/dist/lit/components/divider/index.d.ts +1 -0
  67. package/dist/lit/components/divider/index.js +4 -2
  68. package/dist/lit/components/divider/index.styles.js +41 -0
  69. package/dist/lit/components/empty-state/index.d.ts +1 -0
  70. package/dist/lit/components/empty-state/index.js +4 -2
  71. package/dist/lit/components/empty-state/index.styles.js +83 -0
  72. package/dist/lit/components/expansion-panel/index.d.ts +5 -0
  73. package/dist/lit/components/expansion-panel/index.js +8 -2
  74. package/dist/lit/components/expansion-panel/index.styles.js +134 -0
  75. package/dist/lit/components/field/index.d.ts +4 -0
  76. package/dist/lit/components/field/index.js +9 -4
  77. package/dist/lit/components/field/index.styles.js +237 -0
  78. package/dist/lit/components/file-input/index.d.ts +4 -0
  79. package/dist/lit/components/file-input/index.js +10 -4
  80. package/dist/lit/components/file-input/index.styles.js +271 -0
  81. package/dist/lit/components/form/index.d.ts +4 -0
  82. package/dist/lit/components/form/index.js +7 -2
  83. package/dist/lit/components/form/index.styles.js +43 -0
  84. package/dist/lit/components/grid/index.d.ts +1 -0
  85. package/dist/lit/components/grid/index.js +4 -2
  86. package/dist/lit/components/grid/index.styles.js +67 -0
  87. package/dist/lit/components/kbd/index.d.ts +1 -0
  88. package/dist/lit/components/kbd/index.js +4 -2
  89. package/dist/lit/components/kbd/index.styles.js +49 -0
  90. package/dist/lit/components/list/index.d.ts +4 -0
  91. package/dist/lit/components/list/index.js +7 -2
  92. package/dist/lit/components/list/index.styles.js +29 -0
  93. package/dist/lit/components/list-item/index.d.ts +1 -0
  94. package/dist/lit/components/list-item/index.js +4 -2
  95. package/dist/lit/components/list-item/index.styles.js +133 -0
  96. package/dist/lit/components/menu/index.d.ts +8 -0
  97. package/dist/lit/components/menu/index.js +11 -3
  98. package/dist/lit/components/menu/index.styles.js +108 -0
  99. package/dist/lit/components/multi-select/index.css +156 -0
  100. package/dist/lit/components/multi-select/index.d.ts +70 -0
  101. package/dist/lit/components/multi-select/index.js +497 -0
  102. package/dist/lit/components/multi-select/index.styles.js +170 -0
  103. package/dist/lit/components/navigation-drawer/index.d.ts +4 -0
  104. package/dist/lit/components/navigation-drawer/index.js +7 -2
  105. package/dist/lit/components/navigation-drawer/index.styles.js +128 -0
  106. package/dist/lit/components/overlay/index.d.ts +5 -0
  107. package/dist/lit/components/overlay/index.js +8 -2
  108. package/dist/lit/components/overlay/index.styles.js +185 -0
  109. package/dist/lit/components/pagination/index.d.ts +17 -0
  110. package/dist/lit/components/pagination/index.js +53 -8
  111. package/dist/lit/components/pagination/index.styles.js +116 -0
  112. package/dist/lit/components/popover/index.d.ts +5 -0
  113. package/dist/lit/components/popover/index.js +8 -2
  114. package/dist/lit/components/popover/index.styles.js +48 -0
  115. package/dist/lit/components/primitives/index.js +8 -9
  116. package/dist/lit/components/primitives/index.styles.js +518 -0
  117. package/dist/lit/components/progress/index.d.ts +1 -0
  118. package/dist/lit/components/progress/index.js +4 -2
  119. package/dist/lit/components/progress/index.styles.js +157 -0
  120. package/dist/lit/components/radio-group/index.d.ts +5 -0
  121. package/dist/lit/components/radio-group/index.js +10 -6
  122. package/dist/lit/components/radio-group/index.styles.js +192 -0
  123. package/dist/lit/components/select/index.d.ts +4 -0
  124. package/dist/lit/components/select/index.js +10 -2
  125. package/dist/lit/components/select/index.styles.js +165 -0
  126. package/dist/lit/components/sidebar-item/index.js +8 -9
  127. package/dist/lit/components/sidebar-item/index.styles.js +147 -0
  128. package/dist/lit/components/skeleton/index.d.ts +1 -0
  129. package/dist/lit/components/skeleton/index.js +4 -2
  130. package/dist/lit/components/skeleton/index.styles.js +95 -0
  131. package/dist/lit/components/slider/index.d.ts +5 -0
  132. package/dist/lit/components/slider/index.js +11 -4
  133. package/dist/lit/components/slider/index.styles.js +185 -0
  134. package/dist/lit/components/snackbar/index.d.ts +4 -0
  135. package/dist/lit/components/snackbar/index.js +14 -10
  136. package/dist/lit/components/snackbar/index.styles.js +293 -0
  137. package/dist/lit/components/stack/index.d.ts +1 -0
  138. package/dist/lit/components/stack/index.js +4 -2
  139. package/dist/lit/components/stack/index.styles.js +55 -0
  140. package/dist/lit/components/switch/index.d.ts +1 -0
  141. package/dist/lit/components/switch/index.js +7 -4
  142. package/dist/lit/components/switch/index.styles.js +140 -0
  143. package/dist/lit/components/table/index.d.ts +1 -0
  144. package/dist/lit/components/table/index.js +4 -2
  145. package/dist/lit/components/table/index.styles.js +99 -0
  146. package/dist/lit/components/tabs/index.d.ts +4 -0
  147. package/dist/lit/components/tabs/index.js +8 -4
  148. package/dist/lit/components/tabs/index.styles.js +130 -0
  149. package/dist/lit/components/text-field/index.d.ts +1 -0
  150. package/dist/lit/components/text-field/index.js +7 -2
  151. package/dist/lit/components/text-field/index.styles.js +104 -0
  152. package/dist/lit/components/textarea/index.d.ts +1 -0
  153. package/dist/lit/components/textarea/index.js +7 -2
  154. package/dist/lit/components/textarea/index.styles.js +69 -0
  155. package/dist/lit/components/tooltip/index.d.ts +1 -0
  156. package/dist/lit/components/tooltip/index.js +4 -2
  157. package/dist/lit/components/tooltip/index.styles.js +51 -0
  158. package/dist/lit/components/validation/index.d.ts +6 -0
  159. package/dist/lit/components/validation/index.js +15 -10
  160. package/dist/lit/components/validation/index.styles.js +400 -0
  161. package/dist/lit/index.d.ts +1 -0
  162. package/dist/lit/index.js +1 -0
  163. package/dist/react/XmAlert.d.ts +99 -0
  164. package/dist/react/XmAlert.js +47 -0
  165. package/dist/react/XmAppBar.d.ts +59 -0
  166. package/dist/react/XmAppBar.js +34 -0
  167. package/dist/react/XmArtifact.d.ts +113 -0
  168. package/dist/react/XmArtifact.js +48 -0
  169. package/dist/react/XmArtifactChip.d.ts +56 -0
  170. package/dist/react/XmArtifactChip.js +32 -0
  171. package/dist/react/XmAutocomplete.d.ts +153 -0
  172. package/dist/react/XmAutocomplete.js +70 -0
  173. package/dist/react/XmAvatar.d.ts +71 -0
  174. package/dist/react/XmAvatar.js +40 -0
  175. package/dist/react/XmAvatarGroup.d.ts +59 -0
  176. package/dist/react/XmAvatarGroup.js +34 -0
  177. package/dist/react/XmBadge.d.ts +67 -0
  178. package/dist/react/XmBadge.js +38 -0
  179. package/dist/react/XmBrandGlyph.d.ts +46 -0
  180. package/dist/react/XmBrandGlyph.js +24 -0
  181. package/dist/react/XmBrandMark.d.ts +71 -0
  182. package/dist/react/XmBrandMark.js +40 -0
  183. package/dist/react/XmBreadcrumbs.d.ts +56 -0
  184. package/dist/react/XmBreadcrumbs.js +32 -0
  185. package/dist/react/XmBubble.d.ts +69 -0
  186. package/dist/react/XmBubble.js +38 -0
  187. package/dist/react/XmBubbleActions.d.ts +59 -0
  188. package/dist/react/XmBubbleActions.js +34 -0
  189. package/dist/react/XmBubbleGroup.d.ts +82 -0
  190. package/dist/react/XmBubbleGroup.js +38 -0
  191. package/dist/react/XmButton.d.ts +89 -0
  192. package/dist/react/XmButton.js +48 -0
  193. package/dist/react/XmCard.d.ts +59 -0
  194. package/dist/react/XmCard.js +34 -0
  195. package/dist/react/XmChatShell.d.ts +110 -0
  196. package/dist/react/XmChatShell.js +48 -0
  197. package/dist/react/XmCheckbox.d.ts +145 -0
  198. package/dist/react/XmCheckbox.js +60 -0
  199. package/dist/react/XmChip.d.ts +99 -0
  200. package/dist/react/XmChip.js +48 -0
  201. package/dist/react/XmChipGroup.d.ts +79 -0
  202. package/dist/react/XmChipGroup.js +36 -0
  203. package/dist/react/XmCode.d.ts +55 -0
  204. package/dist/react/XmCode.js +32 -0
  205. package/dist/react/XmComposer.d.ts +123 -0
  206. package/dist/react/XmComposer.js +56 -0
  207. package/dist/react/XmDataTable.d.ts +125 -0
  208. package/dist/react/XmDataTable.js +66 -0
  209. package/dist/react/XmDateRange.d.ts +93 -0
  210. package/dist/react/XmDateRange.js +42 -0
  211. package/dist/react/XmDialog.d.ts +87 -0
  212. package/dist/react/XmDialog.js +41 -0
  213. package/dist/react/XmDivider.d.ts +55 -0
  214. package/dist/react/XmDivider.js +32 -0
  215. package/dist/react/XmEmptyState.d.ts +61 -0
  216. package/dist/react/XmEmptyState.js +34 -0
  217. package/dist/react/XmExpansionPanel.d.ts +101 -0
  218. package/dist/react/XmExpansionPanel.js +49 -0
  219. package/dist/react/XmFileInput.d.ts +151 -0
  220. package/dist/react/XmFileInput.js +70 -0
  221. package/dist/react/XmFileValidationBlock.d.ts +111 -0
  222. package/dist/react/XmFileValidationBlock.js +50 -0
  223. package/dist/react/XmForm.d.ts +91 -0
  224. package/dist/react/XmForm.js +38 -0
  225. package/dist/react/XmGrid.d.ts +59 -0
  226. package/dist/react/XmGrid.js +34 -0
  227. package/dist/react/XmKbd.d.ts +46 -0
  228. package/dist/react/XmKbd.js +24 -0
  229. package/dist/react/XmList.d.ts +83 -0
  230. package/dist/react/XmList.js +38 -0
  231. package/dist/react/XmListItem.d.ts +67 -0
  232. package/dist/react/XmListItem.js +38 -0
  233. package/dist/react/XmMenu.d.ts +98 -0
  234. package/dist/react/XmMenu.js +46 -0
  235. package/dist/react/XmMenuItem.d.ts +63 -0
  236. package/dist/react/XmMenuItem.js +36 -0
  237. package/dist/react/XmMultiSelect.d.ts +161 -0
  238. package/dist/react/XmMultiSelect.js +74 -0
  239. package/dist/react/XmNavigationDrawer.d.ts +93 -0
  240. package/dist/react/XmNavigationDrawer.js +42 -0
  241. package/dist/react/XmOverlay.d.ts +120 -0
  242. package/dist/react/XmOverlay.js +56 -0
  243. package/dist/react/XmPagination.d.ts +117 -0
  244. package/dist/react/XmPagination.js +58 -0
  245. package/dist/react/XmPopover.d.ts +90 -0
  246. package/dist/react/XmPopover.js +42 -0
  247. package/dist/react/XmProgress.d.ts +75 -0
  248. package/dist/react/XmProgress.js +42 -0
  249. package/dist/react/XmRadio.d.ts +88 -0
  250. package/dist/react/XmRadio.js +42 -0
  251. package/dist/react/XmRadioGroup.d.ts +139 -0
  252. package/dist/react/XmRadioGroup.js +58 -0
  253. package/dist/react/XmSelect.d.ts +152 -0
  254. package/dist/react/XmSelect.js +70 -0
  255. package/dist/react/XmSidebarItem.d.ts +75 -0
  256. package/dist/react/XmSidebarItem.js +42 -0
  257. package/dist/react/XmSkeleton.d.ts +71 -0
  258. package/dist/react/XmSkeleton.js +40 -0
  259. package/dist/react/XmSlider.d.ts +160 -0
  260. package/dist/react/XmSlider.js +76 -0
  261. package/dist/react/XmSnackbar.d.ts +110 -0
  262. package/dist/react/XmSnackbar.js +51 -0
  263. package/dist/react/XmStack.d.ts +71 -0
  264. package/dist/react/XmStack.js +40 -0
  265. package/dist/react/XmSwitch.d.ts +136 -0
  266. package/dist/react/XmSwitch.js +58 -0
  267. package/dist/react/XmTab.d.ts +79 -0
  268. package/dist/react/XmTab.js +38 -0
  269. package/dist/react/XmTabPanel.d.ts +55 -0
  270. package/dist/react/XmTabPanel.js +32 -0
  271. package/dist/react/XmTable.d.ts +57 -0
  272. package/dist/react/XmTable.js +32 -0
  273. package/dist/react/XmTabs.d.ts +82 -0
  274. package/dist/react/XmTabs.js +38 -0
  275. package/dist/react/XmTextField.d.ts +147 -0
  276. package/dist/react/XmTextField.js +62 -0
  277. package/dist/react/XmTextarea.d.ts +155 -0
  278. package/dist/react/XmTextarea.js +66 -0
  279. package/dist/react/XmTooltip.d.ts +67 -0
  280. package/dist/react/XmTooltip.js +38 -0
  281. package/dist/react/index.d.ts +59 -0
  282. package/dist/react/index.js +59 -0
  283. package/dist/react/react-utils.js +67 -0
  284. package/package.json +37 -9
  285. package/styles/_base-typography.css +86 -0
  286. package/styles/_primitives.css +54 -0
  287. package/styles/_reset.css +58 -0
  288. package/styles/base.css +23 -0
  289. package/vscode.css-custom-data.json +6 -0
  290. package/vscode.html-custom-data.json +979 -0
@@ -56,9 +56,14 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
56
56
  };
57
57
  import { LitElement, html, nothing } from "lit";
58
58
  import { customElement, property, state } from "lit/decorators.js";
59
- const DATA_TABLE_CSS = new URL("../data-table/index.css", import.meta.url).href;
60
- const PRIMITIVES_CSS = new URL("../primitives/index.css", import.meta.url).href;
59
+ import primitivesSheets from "../primitives/index.styles.js";
60
+ import dataTableSheets from "./index.styles.js";
61
61
  const DEFAULT_PAGE_SIZE = 10;
62
+ /**
63
+ * @fires xm-data-table-page-change - Fired when the page changes (`detail.page`).
64
+ * @fires xm-data-table-sort-change - Fired when the sort changes (`detail.key`, `detail.direction`).
65
+ * @fires xm-data-table-row-click - Fired when a clickable row is activated (`detail.row`, `detail.index`).
66
+ */
62
67
  let XmDataTable = class XmDataTable extends LitElement {
63
68
  constructor() {
64
69
  super(...arguments);
@@ -68,6 +73,17 @@ let XmDataTable = class XmDataTable extends LitElement {
68
73
  this.pageSize = DEFAULT_PAGE_SIZE;
69
74
  this.emptyHeading = "No data";
70
75
  this.emptyText = "";
76
+ /** Server/controlled mode (AD-14): the consumer owns sort + paging. The table
77
+ renders `rows` verbatim, never sorts/slices a copy, derives the page count
78
+ from `total-items` (not `rows.length`), and emits intents only. */
79
+ this.server = false;
80
+ /** Total item count for server-mode paging (pages = ceil(total-items/page-size)). */
81
+ this.totalItems = 0;
82
+ /** Controlled sort indicator for server mode (`{ key, direction }`); reflected,
83
+ never reordered locally. */
84
+ this.sort = null;
85
+ /** Make rows clickable — emits xm-data-table-row-click (AD-15). */
86
+ this.rowClick = false;
71
87
  this._sortKey = null;
72
88
  this._sortDirection = "asc";
73
89
  this._currentPage = 1;
@@ -84,6 +100,9 @@ let XmDataTable = class XmDataTable extends LitElement {
84
100
  }));
85
101
  };
86
102
  }
103
+ // Adopted from the build-generated sheets (scripts/gen-styles.mjs) — no
104
+ // runtime URL fetch (ADR 0012). Cascade order preserved from the old <link>s.
105
+ static { this.styles = [...primitivesSheets, ...dataTableSheets]; }
87
106
  willUpdate(changed) {
88
107
  // Allow declarative JSON in attributes for static HTML authoring (mirrors
89
108
  // xm-table); the @property is attribute:false, so set .columns/.rows as a
@@ -105,11 +124,18 @@ let XmDataTable = class XmDataTable extends LitElement {
105
124
  this.rows = changed.get("rows") ?? [];
106
125
  }
107
126
  }
108
- // Re-clamp the active page whenever the dataset or page size shrinks so the
109
- // current slice is never out of bounds (e.g. after a filter swaps `rows`).
110
- // The clamp moves the page silently from the consumer's view, so emit a
111
- // page-change so a server-mode consumer can reconcile (uncontrolled-out).
112
- if (changed.has("rows") || changed.has("pageSize")) {
127
+ // Controlled sort (server mode, AD-14): reflect the `sort` prop as the
128
+ // indicator; the table never reorders locally.
129
+ if (this.server && changed.has("sort")) {
130
+ this._sortKey = this.sort?.key ?? null;
131
+ this._sortDirection = this.sort?.direction ?? "asc";
132
+ }
133
+ // Client mode only: re-clamp the active page when the dataset/page size
134
+ // shrinks so the slice is never out of bounds (e.g. after a filter swaps
135
+ // `rows`). In server mode the consumer owns paging — never clamp or emit a
136
+ // page-change the user didn't cause, and never derive paging from
137
+ // `rows.length` (AD-14).
138
+ if (!this.server && (changed.has("rows") || changed.has("pageSize"))) {
113
139
  const pages = this._pageCount();
114
140
  const clamped = Math.min(Math.max(this._currentPage, 1), pages);
115
141
  if (clamped !== this._currentPage) {
@@ -124,8 +150,6 @@ let XmDataTable = class XmDataTable extends LitElement {
124
150
  }
125
151
  render() {
126
152
  return html `
127
- <link rel="stylesheet" href="${PRIMITIVES_CSS}" />
128
- <link rel="stylesheet" href="${DATA_TABLE_CSS}" />
129
153
  <style>
130
154
  :host {
131
155
  display: block;
@@ -201,21 +225,37 @@ let XmDataTable = class XmDataTable extends LitElement {
201
225
  }
202
226
  _renderDataRows() {
203
227
  const slice = this._pagedRows();
204
- return html `${slice.map((row) => html `
205
- <tr class="data-table__row">
228
+ const clickable = this.rowClick;
229
+ return html `${slice.map((row, index) => {
230
+ const rowCls = `data-table__row${clickable ? " data-table__row--clickable" : ""}`;
231
+ return html `
232
+ <tr
233
+ class="${rowCls}"
234
+ tabindex=${clickable ? "0" : nothing}
235
+ @click=${clickable
236
+ ? (e) => this._onRowClick(e, row, index)
237
+ : nothing}
238
+ @keydown=${clickable
239
+ ? (e) => this._onRowKey(e, row, index)
240
+ : nothing}
241
+ >
206
242
  ${this.columns.map((col) => {
207
- const numeric = this._isNumericCol(col);
208
- const cls = [
209
- "data-table__cell",
210
- numeric && "data-table__cell--end",
211
- col.muted && "data-table__cell--muted",
212
- ]
213
- .filter(Boolean)
214
- .join(" ");
215
- return html `<td class="${cls}">${row[col.key] ?? ""}</td>`;
216
- })}
243
+ const numeric = this._isNumericCol(col);
244
+ const cls = [
245
+ "data-table__cell",
246
+ numeric && "data-table__cell--end",
247
+ col.mono && "data-table__cell--mono",
248
+ col.muted && "data-table__cell--muted",
249
+ ]
250
+ .filter(Boolean)
251
+ .join(" ");
252
+ // Formatter output is text (Lit auto-escapes) — never markup (ADR 0008).
253
+ const value = col.format ? col.format(row[col.key], row) : row[col.key] ?? "";
254
+ return html `<td class="${cls}">${value}</td>`;
255
+ })}
217
256
  </tr>
218
- `)}`;
257
+ `;
258
+ })}`;
219
259
  }
220
260
  // Loading: one skeleton row per page-size, each cell a composed <xm-skeleton>
221
261
  // line laid on the same column grid. The skeleton owns its gradient-free pulse;
@@ -273,7 +313,12 @@ let XmDataTable = class XmDataTable extends LitElement {
273
313
  }
274
314
  // ── State helpers ───────────────────────────────────────────────
275
315
  _isEmpty() {
276
- return !this.loading && this.rows.length === 0;
316
+ if (this.loading)
317
+ return false;
318
+ // Server mode: "empty" means the consumer's total is 0 — never `rows.length`.
319
+ // A transient empty page (rows momentarily empty while a page loads, with
320
+ // total-items > 0) must NOT collapse to the empty state or hide the pager (AD-14).
321
+ return this.server ? this.totalItems === 0 : this.rows.length === 0;
277
322
  }
278
323
  _isNumericCol(col) {
279
324
  if (col.align === "end")
@@ -287,7 +332,10 @@ let XmDataTable = class XmDataTable extends LitElement {
287
332
  return Number.isFinite(n) && n > 0 ? n : DEFAULT_PAGE_SIZE;
288
333
  }
289
334
  _pageCount() {
290
- return Math.max(1, Math.ceil(this.rows.length / this._effectivePageSize()));
335
+ // Server mode derives the page count from the consumer's total item count,
336
+ // never from the single rendered page in `rows` (AD-14).
337
+ const count = this.server ? this.totalItems : this.rows.length;
338
+ return Math.max(1, Math.ceil(count / this._effectivePageSize()));
291
339
  }
292
340
  // Sort the FULL dataset (non-destructive copy), THEN slice the active page.
293
341
  _sortedRows() {
@@ -304,6 +352,10 @@ let XmDataTable = class XmDataTable extends LitElement {
304
352
  return [...this.rows].sort((a, b) => this._compare(valueOf(a), valueOf(b)) * dir);
305
353
  }
306
354
  _pagedRows() {
355
+ // Server mode: render the consumer-supplied page verbatim — no client
356
+ // sort, no client slice (AD-14, counters SM-C2).
357
+ if (this.server)
358
+ return this.rows;
307
359
  const size = this._effectivePageSize();
308
360
  const start = (this._currentPage - 1) * size;
309
361
  return this._sortedRows().slice(start, start + size);
@@ -333,23 +385,45 @@ let XmDataTable = class XmDataTable extends LitElement {
333
385
  _toggleSort(col) {
334
386
  if (!col.sortable)
335
387
  return;
336
- if (this._sortKey === col.key) {
337
- this._sortDirection = this._sortDirection === "asc" ? "desc" : "asc";
338
- }
339
- else {
340
- this._sortKey = col.key;
341
- this._sortDirection = "asc";
388
+ const nextDirection = this._sortKey === col.key && this._sortDirection === "asc" ? "desc" : "asc";
389
+ const detail = { key: col.key, direction: nextDirection };
390
+ // Client mode applies the sort locally (uncontrolled). Server mode emits
391
+ // only — the consumer drives the `sort` prop, which reflects back as the
392
+ // indicator (AD-14); the table never reorders locally.
393
+ if (!this.server) {
394
+ this._sortKey = detail.key;
395
+ this._sortDirection = detail.direction;
342
396
  }
343
- const detail = {
344
- key: this._sortKey,
345
- direction: this._sortDirection,
346
- };
347
397
  this.dispatchEvent(new CustomEvent("xm-data-table-sort-change", {
348
398
  detail,
349
399
  bubbles: true,
350
400
  composed: true,
351
401
  }));
352
402
  }
403
+ _onRowClick(e, row, index) {
404
+ // Don't fire when the activation originates on an interactive descendant (AD-15).
405
+ const interactive = e.composedPath().some((t) => t instanceof Element &&
406
+ t !== e.currentTarget &&
407
+ t.matches?.('a[href],button,input,select,textarea,' +
408
+ '[role="button"],[role="link"],[role="checkbox"],[role="switch"],[role="menuitem"],[role="tab"],' +
409
+ '[tabindex]:not([tabindex="-1"])'));
410
+ if (interactive)
411
+ return;
412
+ this._emitRowClick(row, index);
413
+ }
414
+ _onRowKey(e, row, index) {
415
+ if (e.key === "Enter" || e.key === " " || e.key === "Spacebar") {
416
+ e.preventDefault();
417
+ this._emitRowClick(row, index);
418
+ }
419
+ }
420
+ _emitRowClick(row, index) {
421
+ this.dispatchEvent(new CustomEvent("xm-data-table-row-click", {
422
+ detail: { row, index },
423
+ bubbles: true,
424
+ composed: true,
425
+ }));
426
+ }
353
427
  _onHeaderKey(e, col) {
354
428
  if (e.key === "Enter" || e.key === " " || e.key === "Spacebar") {
355
429
  e.preventDefault();
@@ -375,6 +449,18 @@ __decorate([
375
449
  __decorate([
376
450
  property({ type: String, attribute: "empty-text" })
377
451
  ], XmDataTable.prototype, "emptyText", void 0);
452
+ __decorate([
453
+ property({ type: Boolean, reflect: true })
454
+ ], XmDataTable.prototype, "server", void 0);
455
+ __decorate([
456
+ property({ type: Number, attribute: "total-items" })
457
+ ], XmDataTable.prototype, "totalItems", void 0);
458
+ __decorate([
459
+ property({ attribute: false })
460
+ ], XmDataTable.prototype, "sort", void 0);
461
+ __decorate([
462
+ property({ type: Boolean, attribute: "row-click" })
463
+ ], XmDataTable.prototype, "rowClick", void 0);
378
464
  __decorate([
379
465
  state()
380
466
  ], XmDataTable.prototype, "_sortKey", void 0);
@@ -0,0 +1,198 @@
1
+ // GENERATED by scripts/gen-styles.mjs — do not edit. Source: lit/components/data-table/index.css
2
+ // SSR-safe: constructable stylesheets need the DOM, so in a non-DOM context
3
+ // (Node/SSR import) this exports [] instead of throwing. The CSS self-declares
4
+ // the @layer order so the override contract holds even without ./base (AD-2).
5
+ let sheets = [];
6
+ if (typeof CSSStyleSheet !== "undefined") {
7
+ const sheet = new CSSStyleSheet();
8
+ sheet.replaceSync(`@layer reset, base, tokens, components, utilities;
9
+ @layer components {
10
+ /* ============================================
11
+ Data table — the interactive sibling of <xm-table>.
12
+
13
+ Mirrors xm-table's static chrome (1px --md-sys-color-outline-variant
14
+ hairlines, sentence-case headers, numeric right-align + tabular figures,
15
+ number + unit carry a space "412 KB"), then layers in sort, paging, loading,
16
+ and empty states.
17
+
18
+ It sits on ONE surface family — surface* with ink --md-sys-color-on-surface
19
+ (AD-13). Region differentiation is the hairline rule + an optional
20
+ surface-container raise on the header, never a status hue (AD-11). No
21
+ --md-sys-color-error* anywhere; the single coral accent
22
+ (--md-sys-color-primary) marks the active sort.
23
+
24
+ BEM block: \`data-table\`. Registered in scripts/check-bem.sh STRICT_BLOCKS.
25
+ Elements: __head, __row, __cell, __header-cell, __header-label, __sort,
26
+ __sort-icon, __footer, __pagination, __empty. Modifiers: __cell--end,
27
+ __cell--muted, __header-cell--end / --sortable / --active,
28
+ __row--skeleton / --empty.
29
+ ============================================ */
30
+
31
+ .data-table {
32
+ width: 100%;
33
+ border-collapse: collapse;
34
+ background: transparent;
35
+ color: var(--md-sys-color-on-surface);
36
+ font-family: var(--md-sys-typescale-body-medium-font);
37
+ font-size: var(--md-sys-typescale-body-medium-size);
38
+ line-height: var(--md-sys-typescale-body-medium-line-height);
39
+ border: 1px solid var(--md-sys-color-outline-variant);
40
+ border-radius: var(--md-sys-shape-corner-medium);
41
+ overflow: hidden;
42
+ }
43
+
44
+ .data-table__head {
45
+ background: var(--md-sys-color-surface-container-low);
46
+ }
47
+
48
+ .data-table__header-cell {
49
+ text-align: start;
50
+ padding: 0;
51
+ border-bottom: 1px solid var(--md-sys-color-outline-variant);
52
+ color: var(--md-sys-color-on-surface);
53
+ font-family: var(--md-sys-typescale-label-large-font);
54
+ font-size: var(--md-sys-typescale-label-medium-size);
55
+ font-weight: 600;
56
+ letter-spacing: 0;
57
+ white-space: nowrap;
58
+ }
59
+
60
+ .data-table__header-label {
61
+ display: inline-block;
62
+ }
63
+
64
+ /* The static label sits with the same padding the sortable hit-area carries,
65
+ so sortable and inert headers align on a shared baseline. */
66
+ .data-table__header-cell > .data-table__header-label {
67
+ padding: var(--s-3) var(--s-4);
68
+ }
69
+
70
+ /* Sortable header: a focusable in-cell control that fills the cell so the whole
71
+ header is the hit target. Hover/active swap real tokens — no filter/opacity. */
72
+ .data-table__sort {
73
+ display: flex;
74
+ align-items: center;
75
+ gap: var(--s-2);
76
+ box-sizing: border-box;
77
+ width: 100%;
78
+ padding: var(--s-3) var(--s-4);
79
+ cursor: pointer;
80
+ user-select: none;
81
+ color: inherit;
82
+ border-radius: var(--md-sys-shape-corner-small);
83
+ outline: none;
84
+ }
85
+
86
+ .data-table__header-cell--sortable .data-table__sort:hover {
87
+ background: color-mix(
88
+ in oklab,
89
+ var(--md-sys-color-on-surface) var(--md-sys-state-hover-state-layer-opacity),
90
+ transparent
91
+ );
92
+ }
93
+
94
+ .data-table__header-cell--sortable .data-table__sort:active {
95
+ background: color-mix(
96
+ in oklab,
97
+ var(--md-sys-color-on-surface) var(--md-sys-state-pressed-state-layer-opacity),
98
+ transparent
99
+ );
100
+ }
101
+
102
+ .data-table__header-cell--sortable .data-table__sort:focus-visible {
103
+ box-shadow: var(--xm-state-focus-ring);
104
+ }
105
+
106
+ /* The active sorted column reads in the coral accent — the only emphasis (AD-11). */
107
+ .data-table__header-cell--active {
108
+ color: var(--md-sys-color-primary);
109
+ }
110
+
111
+ .data-table__sort-icon {
112
+ display: inline-flex;
113
+ align-items: center;
114
+ color: var(--md-sys-color-primary);
115
+ }
116
+
117
+ /* End-aligned (numeric) headers push their content to the trailing edge. */
118
+ .data-table__header-cell--end .data-table__sort,
119
+ .data-table__header-cell--end > .data-table__header-label {
120
+ justify-content: flex-end;
121
+ text-align: end;
122
+ }
123
+
124
+ .data-table__row + .data-table__row .data-table__cell {
125
+ border-top: 1px solid var(--md-sys-color-outline-variant);
126
+ }
127
+
128
+ .data-table__cell {
129
+ padding: var(--s-3) var(--s-4);
130
+ text-align: start;
131
+ vertical-align: middle;
132
+ color: var(--md-sys-color-on-surface);
133
+ }
134
+
135
+ .data-table__cell--muted {
136
+ color: var(--md-sys-color-on-surface-variant);
137
+ }
138
+
139
+ /* Monospace/tabular cells (per-column \`mono\`) — IDs, hashes, code-like values. */
140
+ .data-table__cell--mono {
141
+ font-family: var(--xm-typescale-mono-font);
142
+ font-size: var(--xm-typescale-mono-size);
143
+ font-weight: var(--xm-typescale-mono-weight);
144
+ line-height: var(--xm-typescale-mono-line-height);
145
+ font-variant-numeric: tabular-nums;
146
+ }
147
+
148
+ /* Clickable rows (row-click, AD-15) — keyboard-focusable; pointer + focus ring. */
149
+ .data-table__row--clickable {
150
+ cursor: pointer;
151
+ }
152
+ .data-table__row--clickable:focus-visible {
153
+ outline: none;
154
+ box-shadow: var(--xm-state-focus-ring);
155
+ }
156
+
157
+ /* Numeric — right-aligned, tabular figures so digits line up; the unit carries
158
+ a space in the value ("412 KB"). Matches xm-table (NFR-22 / UX-DR4). */
159
+ .data-table__header-cell--end,
160
+ .data-table__cell--end {
161
+ text-align: end;
162
+ font-variant-numeric: tabular-nums;
163
+ font-feature-settings: "tnum" 1;
164
+ }
165
+
166
+ .data-table__row:not(.data-table__row--skeleton):not(.data-table__row--empty):hover
167
+ .data-table__cell {
168
+ background: color-mix(
169
+ in oklab,
170
+ var(--md-sys-color-on-surface) var(--md-sys-state-hover-state-layer-opacity),
171
+ transparent
172
+ );
173
+ }
174
+
175
+ /* Loading rows host composed <xm-skeleton> lines on the same column grid; the
176
+ skeleton owns the gradient-free pulse (AD-12). No row hover under load. */
177
+ .data-table__row--skeleton .data-table__cell {
178
+ padding-block: calc(var(--s-3) + 1px);
179
+ }
180
+
181
+ /* Empty: a single spanning cell hosting the composed <xm-empty-state>; never a
182
+ blank box (FR-161). The empty-state inherits the host on-* ink (AD-13). */
183
+ .data-table__empty {
184
+ padding: var(--s-8) var(--s-4);
185
+ text-align: center;
186
+ }
187
+
188
+ /* Footer carries the composed <xm-pagination>, right-aligned under the grid. */
189
+ .data-table__footer {
190
+ display: flex;
191
+ justify-content: flex-end;
192
+ padding-top: var(--s-3);
193
+ }
194
+
195
+ }`);
196
+ sheets = [sheet];
197
+ }
198
+ export default sheets;
@@ -4,7 +4,11 @@ export interface DateRangeChangeDetail {
4
4
  from: string | null;
5
5
  to: string | null;
6
6
  }
7
+ /**
8
+ * @fires xm-date-range-change - Fired when the selected date range changes.
9
+ */
7
10
  export declare class XmDateRange extends LitElement {
11
+ static styles: CSSStyleSheet[];
8
12
  from: string | null;
9
13
  to: string | null;
10
14
  placeholder: string;
@@ -53,7 +53,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
53
53
  };
54
54
  import { LitElement, html, svg, nothing } from "lit";
55
55
  import { customElement, property, state, query } from "lit/decorators.js";
56
- const DR_CSS = new URL("../date-range/index.css", import.meta.url).href;
56
+ import dateRangeSheets from "./index.styles.js";
57
57
  let drSeq = 0;
58
58
  const PRESETS = [
59
59
  { id: "today", label: "Today" },
@@ -146,6 +146,9 @@ const SHORT_FMT = new Intl.DateTimeFormat(undefined, {
146
146
  day: "numeric",
147
147
  year: "numeric",
148
148
  });
149
+ /**
150
+ * @fires xm-date-range-change - Fired when the selected date range changes.
151
+ */
149
152
  let XmDateRange = class XmDateRange extends LitElement {
150
153
  constructor() {
151
154
  super(...arguments);
@@ -179,6 +182,9 @@ let XmDateRange = class XmDateRange extends LitElement {
179
182
  }
180
183
  };
181
184
  }
185
+ // Adopted from the build-generated sheets (scripts/gen-styles.mjs) — no
186
+ // runtime URL fetch (ADR 0012). Cascade order preserved from the old <link>s.
187
+ static { this.styles = [...dateRangeSheets]; }
182
188
  connectedCallback() {
183
189
  super.connectedCallback();
184
190
  document.addEventListener("pointerdown", this._onDocPointer, true);
@@ -430,7 +436,6 @@ let XmDateRange = class XmDateRange extends LitElement {
430
436
  const labelId = `${this._id}-title`;
431
437
  const triggerCls = `date-range__trigger${this.open ? " date-range__trigger--open" : ""}`;
432
438
  return html `
433
- <link rel="stylesheet" href="${DR_CSS}" />
434
439
  <style>
435
440
  :host { display: inline-block; }
436
441
  :host([hidden]) { display: none; }