@xmesh/system-design 0.0.1

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 (175) hide show
  1. package/README.md +472 -0
  2. package/assets/brand-lockup-dark.svg +9 -0
  3. package/assets/brand-lockup-light.svg +9 -0
  4. package/assets/brand-mark.svg +9 -0
  5. package/colors_and_type.css +11 -0
  6. package/dist/lit/components/alert/index.css +201 -0
  7. package/dist/lit/components/alert/index.d.ts +25 -0
  8. package/dist/lit/components/alert/index.js +191 -0
  9. package/dist/lit/components/app-bar/index.css +80 -0
  10. package/dist/lit/components/app-bar/index.d.ts +19 -0
  11. package/dist/lit/components/app-bar/index.js +120 -0
  12. package/dist/lit/components/artifact/index.css +166 -0
  13. package/dist/lit/components/artifact/index.d.ts +37 -0
  14. package/dist/lit/components/artifact/index.js +294 -0
  15. package/dist/lit/components/autocomplete/index.css +171 -0
  16. package/dist/lit/components/autocomplete/index.d.ts +47 -0
  17. package/dist/lit/components/autocomplete/index.js +404 -0
  18. package/dist/lit/components/avatar/index.css +62 -0
  19. package/dist/lit/components/avatar/index.d.ts +19 -0
  20. package/dist/lit/components/avatar/index.js +112 -0
  21. package/dist/lit/components/avatar-group/index.css +60 -0
  22. package/dist/lit/components/avatar-group/index.d.ts +19 -0
  23. package/dist/lit/components/avatar-group/index.js +97 -0
  24. package/dist/lit/components/badge/index.css +72 -0
  25. package/dist/lit/components/badge/index.d.ts +18 -0
  26. package/dist/lit/components/badge/index.js +115 -0
  27. package/dist/lit/components/brand-mark/index.css +109 -0
  28. package/dist/lit/components/brand-mark/index.d.ts +24 -0
  29. package/dist/lit/components/brand-mark/index.js +116 -0
  30. package/dist/lit/components/breadcrumbs/index.css +91 -0
  31. package/dist/lit/components/breadcrumbs/index.d.ts +19 -0
  32. package/dist/lit/components/breadcrumbs/index.js +104 -0
  33. package/dist/lit/components/bubble/index.css +182 -0
  34. package/dist/lit/components/bubble/index.d.ts +72 -0
  35. package/dist/lit/components/bubble/index.js +617 -0
  36. package/dist/lit/components/button/index.css +342 -0
  37. package/dist/lit/components/button/index.d.ts +32 -0
  38. package/dist/lit/components/button/index.js +202 -0
  39. package/dist/lit/components/card/index.css +99 -0
  40. package/dist/lit/components/card/index.d.ts +20 -0
  41. package/dist/lit/components/card/index.js +133 -0
  42. package/dist/lit/components/chat/index.css +292 -0
  43. package/dist/lit/components/chat/index.d.ts +74 -0
  44. package/dist/lit/components/chat/index.js +589 -0
  45. package/dist/lit/components/checkbox/index.css +126 -0
  46. package/dist/lit/components/checkbox/index.d.ts +21 -0
  47. package/dist/lit/components/checkbox/index.js +138 -0
  48. package/dist/lit/components/chip/index.css +145 -0
  49. package/dist/lit/components/chip/index.d.ts +30 -0
  50. package/dist/lit/components/chip/index.js +230 -0
  51. package/dist/lit/components/chip-group/index.css +19 -0
  52. package/dist/lit/components/chip-group/index.d.ts +24 -0
  53. package/dist/lit/components/chip-group/index.js +171 -0
  54. package/dist/lit/components/code/index.css +42 -0
  55. package/dist/lit/components/code/index.d.ts +12 -0
  56. package/dist/lit/components/code/index.js +68 -0
  57. package/dist/lit/components/composer/index.css +548 -0
  58. package/dist/lit/components/composer/index.d.ts +67 -0
  59. package/dist/lit/components/composer/index.js +713 -0
  60. package/dist/lit/components/data-table/index.css +166 -0
  61. package/dist/lit/components/data-table/index.d.ts +55 -0
  62. package/dist/lit/components/data-table/index.js +390 -0
  63. package/dist/lit/components/dialog/index.css +124 -0
  64. package/dist/lit/components/dialog/index.d.ts +24 -0
  65. package/dist/lit/components/dialog/index.js +199 -0
  66. package/dist/lit/components/divider/index.css +27 -0
  67. package/dist/lit/components/divider/index.d.ts +13 -0
  68. package/dist/lit/components/divider/index.js +67 -0
  69. package/dist/lit/components/empty-state/index.css +69 -0
  70. package/dist/lit/components/empty-state/index.d.ts +21 -0
  71. package/dist/lit/components/empty-state/index.js +123 -0
  72. package/dist/lit/components/expansion-panel/index.css +120 -0
  73. package/dist/lit/components/expansion-panel/index.d.ts +22 -0
  74. package/dist/lit/components/expansion-panel/index.js +174 -0
  75. package/dist/lit/components/field/index.css +223 -0
  76. package/dist/lit/components/field/index.d.ts +106 -0
  77. package/dist/lit/components/field/index.js +388 -0
  78. package/dist/lit/components/file-input/index.css +257 -0
  79. package/dist/lit/components/file-input/index.d.ts +30 -0
  80. package/dist/lit/components/file-input/index.js +298 -0
  81. package/dist/lit/components/form/index.css +29 -0
  82. package/dist/lit/components/form/index.d.ts +38 -0
  83. package/dist/lit/components/form/index.js +192 -0
  84. package/dist/lit/components/grid/index.css +53 -0
  85. package/dist/lit/components/grid/index.d.ts +14 -0
  86. package/dist/lit/components/grid/index.js +82 -0
  87. package/dist/lit/components/kbd/index.css +35 -0
  88. package/dist/lit/components/kbd/index.d.ts +11 -0
  89. package/dist/lit/components/kbd/index.js +43 -0
  90. package/dist/lit/components/list/index.css +15 -0
  91. package/dist/lit/components/list/index.d.ts +28 -0
  92. package/dist/lit/components/list/index.js +188 -0
  93. package/dist/lit/components/list-item/index.css +119 -0
  94. package/dist/lit/components/list-item/index.d.ts +20 -0
  95. package/dist/lit/components/list-item/index.js +127 -0
  96. package/dist/lit/components/menu/index.css +94 -0
  97. package/dist/lit/components/menu/index.d.ts +47 -0
  98. package/dist/lit/components/menu/index.js +386 -0
  99. package/dist/lit/components/navigation-drawer/index.css +114 -0
  100. package/dist/lit/components/navigation-drawer/index.d.ts +29 -0
  101. package/dist/lit/components/navigation-drawer/index.js +218 -0
  102. package/dist/lit/components/overlay/index.css +171 -0
  103. package/dist/lit/components/overlay/index.d.ts +65 -0
  104. package/dist/lit/components/overlay/index.js +566 -0
  105. package/dist/lit/components/pagination/index.css +102 -0
  106. package/dist/lit/components/pagination/index.d.ts +22 -0
  107. package/dist/lit/components/pagination/index.js +184 -0
  108. package/dist/lit/components/primitives/index.css +504 -0
  109. package/dist/lit/components/primitives/index.d.ts +25 -0
  110. package/dist/lit/components/primitives/index.js +283 -0
  111. package/dist/lit/components/progress/index.css +143 -0
  112. package/dist/lit/components/progress/index.d.ts +23 -0
  113. package/dist/lit/components/progress/index.js +180 -0
  114. package/dist/lit/components/radio-group/index.css +178 -0
  115. package/dist/lit/components/radio-group/index.d.ts +35 -0
  116. package/dist/lit/components/radio-group/index.js +292 -0
  117. package/dist/lit/components/select/index.css +151 -0
  118. package/dist/lit/components/select/index.d.ts +50 -0
  119. package/dist/lit/components/select/index.js +390 -0
  120. package/dist/lit/components/sidebar-item/index.css +133 -0
  121. package/dist/lit/components/sidebar-item/index.d.ts +20 -0
  122. package/dist/lit/components/sidebar-item/index.js +105 -0
  123. package/dist/lit/components/skeleton/index.css +81 -0
  124. package/dist/lit/components/skeleton/index.d.ts +19 -0
  125. package/dist/lit/components/skeleton/index.js +119 -0
  126. package/dist/lit/components/slider/index.css +171 -0
  127. package/dist/lit/components/slider/index.d.ts +36 -0
  128. package/dist/lit/components/slider/index.js +302 -0
  129. package/dist/lit/components/snackbar/index.css +279 -0
  130. package/dist/lit/components/snackbar/index.d.ts +33 -0
  131. package/dist/lit/components/snackbar/index.js +195 -0
  132. package/dist/lit/components/stack/index.css +41 -0
  133. package/dist/lit/components/stack/index.d.ts +20 -0
  134. package/dist/lit/components/stack/index.js +103 -0
  135. package/dist/lit/components/switch/index.css +126 -0
  136. package/dist/lit/components/switch/index.d.ts +17 -0
  137. package/dist/lit/components/switch/index.js +116 -0
  138. package/dist/lit/components/table/index.css +85 -0
  139. package/dist/lit/components/table/index.d.ts +25 -0
  140. package/dist/lit/components/table/index.js +139 -0
  141. package/dist/lit/components/tabs/index.css +116 -0
  142. package/dist/lit/components/tabs/index.d.ts +49 -0
  143. package/dist/lit/components/tabs/index.js +320 -0
  144. package/dist/lit/components/text-field/index.css +90 -0
  145. package/dist/lit/components/text-field/index.d.ts +17 -0
  146. package/dist/lit/components/text-field/index.js +101 -0
  147. package/dist/lit/components/textarea/index.css +55 -0
  148. package/dist/lit/components/textarea/index.d.ts +26 -0
  149. package/dist/lit/components/textarea/index.js +124 -0
  150. package/dist/lit/components/tooltip/index.css +37 -0
  151. package/dist/lit/components/tooltip/index.d.ts +31 -0
  152. package/dist/lit/components/tooltip/index.js +196 -0
  153. package/dist/lit/components/validation/index.css +386 -0
  154. package/dist/lit/components/validation/index.d.ts +45 -0
  155. package/dist/lit/components/validation/index.js +318 -0
  156. package/dist/lit/index.d.ts +50 -0
  157. package/dist/lit/index.js +59 -0
  158. package/package.json +81 -0
  159. package/styles/README.md +346 -0
  160. package/styles/_elevation.css +24 -0
  161. package/styles/_fonts.css +6 -0
  162. package/styles/_layout.css +37 -0
  163. package/styles/_primitives.css +154 -0
  164. package/styles/_scroll.css +75 -0
  165. package/styles/_semantic.css +146 -0
  166. package/styles/_space.css +61 -0
  167. package/styles/_type.css +139 -0
  168. package/styles/_xmesh-extensions.css +232 -0
  169. package/styles/index.css +44 -0
  170. package/styles/md3/_color.css +102 -0
  171. package/styles/md3/_elevation.css +26 -0
  172. package/styles/md3/_motion.css +35 -0
  173. package/styles/md3/_shape.css +22 -0
  174. package/styles/md3/_state.css +22 -0
  175. package/styles/md3/_type.css +111 -0
@@ -0,0 +1,283 @@
1
+ /*
2
+ primitives/index.ts — Lit port of components/primitives/index.jsx.
3
+
4
+ Phase 1 scope: only the pieces <xm-button> needs at runtime, plus the
5
+ named icon elements referenced from preview/buttons.html on the React
6
+ side. The full primitive library (Field, Input, Pill, Badge, etc.) is
7
+ ported in later phases when other components require them.
8
+
9
+ Design rules (mirror the React port):
10
+ • Light DOM (createRenderRoot returns this) so existing CSS in
11
+ components/primitives/index.css and components/button/index.css
12
+ keeps targeting the same .ds-icon / .ds-spinner / .btn classes.
13
+ • Class names rendered identically to the JSX output.
14
+ • SVG path data copied verbatim from index.jsx — same shape, same
15
+ stroke widths, same default sizes.
16
+ */
17
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
18
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
19
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
20
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
21
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
22
+ };
23
+ import { LitElement, html, svg, nothing } from "lit";
24
+ import { customElement, property } from "lit/decorators.js";
25
+ class LightElement extends LitElement {
26
+ createRenderRoot() {
27
+ return this;
28
+ }
29
+ }
30
+ /* ─────────────────────────────────────────────────────────────
31
+ <xm-icon> — sized SVG container, color via currentColor.
32
+ Phase 1 scope: kept minimal — accepts no children in light-DOM
33
+ mode (native <slot> projection requires shadow DOM). Each named
34
+ icon below emits its own complete <svg>, so this base element
35
+ exists primarily for parity with the React Icon primitive.
36
+ Phase 2 should reconsider whether xm-icon should switch to
37
+ shadow DOM with a real <slot> for path content.
38
+ ─────────────────────────────────────────────────────────────*/
39
+ let XmIcon = class XmIcon extends LightElement {
40
+ constructor() {
41
+ super(...arguments);
42
+ this.size = 16;
43
+ this.viewBox = "0 0 24 24";
44
+ this.strokeWidth = 1.8;
45
+ this.fill = "none";
46
+ this.title = "";
47
+ }
48
+ render() {
49
+ const t = this.title;
50
+ return html `
51
+ <svg
52
+ width="${this.size}"
53
+ height="${this.size}"
54
+ viewBox="${this.viewBox}"
55
+ fill="${this.fill}"
56
+ stroke="currentColor"
57
+ stroke-width="${this.strokeWidth}"
58
+ stroke-linecap="round"
59
+ stroke-linejoin="round"
60
+ class="ds-icon"
61
+ aria-hidden="${t ? nothing : "true"}"
62
+ role="${t ? "img" : nothing}"
63
+ >
64
+ ${t ? svg `<title>${t}</title>` : nothing}
65
+ </svg>
66
+ `;
67
+ }
68
+ };
69
+ __decorate([
70
+ property({ type: Number })
71
+ ], XmIcon.prototype, "size", void 0);
72
+ __decorate([
73
+ property({ type: String, attribute: "view-box" })
74
+ ], XmIcon.prototype, "viewBox", void 0);
75
+ __decorate([
76
+ property({ type: Number, attribute: "stroke-width" })
77
+ ], XmIcon.prototype, "strokeWidth", void 0);
78
+ __decorate([
79
+ property({ type: String })
80
+ ], XmIcon.prototype, "fill", void 0);
81
+ __decorate([
82
+ property({ type: String })
83
+ ], XmIcon.prototype, "title", void 0);
84
+ XmIcon = __decorate([
85
+ customElement("xm-icon")
86
+ ], XmIcon);
87
+ /* ─────────────────────────────────────────────────────────────
88
+ <xm-spinner> — circular indeterminate spinner. Used by Button
89
+ for the loading state. Mirrors Spinner({ size }) in the JSX:
90
+ a <span class="ds-spinner btn__spinner"> sized via inline style.
91
+ ─────────────────────────────────────────────────────────────*/
92
+ let XmSpinner = class XmSpinner extends LightElement {
93
+ constructor() {
94
+ super(...arguments);
95
+ this.size = 14;
96
+ this.className = "";
97
+ }
98
+ render() {
99
+ const cls = `ds-spinner ${this.className}`.trim();
100
+ return html `
101
+ <span
102
+ class="${cls}"
103
+ role="status"
104
+ aria-label="Loading"
105
+ style="width:${this.size}px;height:${this.size}px;display:inline-block;"
106
+ ></span>
107
+ `;
108
+ }
109
+ };
110
+ __decorate([
111
+ property({ type: Number })
112
+ ], XmSpinner.prototype, "size", void 0);
113
+ __decorate([
114
+ property({ type: String, attribute: "class-name" })
115
+ ], XmSpinner.prototype, "className", void 0);
116
+ XmSpinner = __decorate([
117
+ customElement("xm-spinner")
118
+ ], XmSpinner);
119
+ const namedIcon = (tag, defaults, paths) => {
120
+ class NamedIcon extends LightElement {
121
+ constructor() {
122
+ super(...arguments);
123
+ this.size = defaults.size ?? 16;
124
+ this.strokeWidth = defaults.strokeWidth ?? 1.8;
125
+ }
126
+ render() {
127
+ return html `
128
+ <svg
129
+ width="${this.size}"
130
+ height="${this.size}"
131
+ viewBox="0 0 24 24"
132
+ fill="none"
133
+ stroke="currentColor"
134
+ stroke-width="${this.strokeWidth}"
135
+ stroke-linecap="round"
136
+ stroke-linejoin="round"
137
+ class="ds-icon"
138
+ aria-hidden="true"
139
+ >
140
+ ${paths()}
141
+ </svg>
142
+ `;
143
+ }
144
+ }
145
+ __decorate([
146
+ property({ type: Number })
147
+ ], NamedIcon.prototype, "size", void 0);
148
+ __decorate([
149
+ property({ type: Number, attribute: "stroke-width" })
150
+ ], NamedIcon.prototype, "strokeWidth", void 0);
151
+ if (!customElements.get(tag))
152
+ customElements.define(tag, NamedIcon);
153
+ return NamedIcon;
154
+ };
155
+ namedIcon("xm-regenerate-icon", { size: 16, strokeWidth: 1.6 }, () => svg `
156
+ <path d="M3 12a9 9 0 1 0 3-6.7" />
157
+ <path d="M3 4v5h5" />
158
+ `);
159
+ namedIcon("xm-copy-icon", { size: 16, strokeWidth: 1.6 }, () => svg `
160
+ <rect x="9" y="9" width="11" height="11" rx="2" />
161
+ <path d="M5 15V5a2 2 0 0 1 2-2h10" />
162
+ `);
163
+ namedIcon("xm-check-icon", { size: 16, strokeWidth: 1.8 }, () => svg `
164
+ <polyline points="20 6 9 17 4 12" />
165
+ `);
166
+ namedIcon("xm-trace-icon", { size: 16, strokeWidth: 1.6 }, () => svg `
167
+ <path d="M8 6V4a4 4 0 0 1 8 0v2" />
168
+ <rect x="6" y="6" width="12" height="13" rx="6" />
169
+ <path d="M12 11v8" />
170
+ <path d="M3 11h3" />
171
+ <path d="M18 11h3" />
172
+ <path d="M3 18h3" />
173
+ <path d="M18 18h3" />
174
+ <path d="M3 14h3" />
175
+ <path d="M18 14h3" />
176
+ `);
177
+ namedIcon("xm-panel-icon", { size: 16, strokeWidth: 1.8 }, () => svg `
178
+ <rect x="3" y="4" width="18" height="16" rx="2" />
179
+ <path d="M9 4v16" />
180
+ `);
181
+ namedIcon("xm-plus-icon", { size: 14, strokeWidth: 2.2 }, () => svg `
182
+ <path d="M12 5v14M5 12h14" />
183
+ `);
184
+ namedIcon("xm-search-icon", { size: 14, strokeWidth: 2 }, () => svg `
185
+ <circle cx="11" cy="11" r="7" />
186
+ <path d="M21 21l-4.3-4.3" />
187
+ `);
188
+ namedIcon("xm-share-icon", { size: 15, strokeWidth: 1.8 }, () => svg `
189
+ <path d="M4 12v7a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-7" />
190
+ <path d="M16 6l-4-4-4 4" />
191
+ <path d="M12 2v14" />
192
+ `);
193
+ namedIcon("xm-settings-icon", { size: 17, strokeWidth: 1.8 }, () => svg `
194
+ <circle cx="12" cy="12" r="3" />
195
+ <path d="M19.4 15a1.7 1.7 0 0 0 .3 1.8l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.7 1.7 0 0 0-1.8-.3 1.7 1.7 0 0 0-1 1.5V21a2 2 0 1 1-4 0v-.1a1.7 1.7 0 0 0-1-1.5 1.7 1.7 0 0 0-1.8.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.7 1.7 0 0 0 .3-1.8 1.7 1.7 0 0 0-1.5-1H3a2 2 0 1 1 0-4h.1a1.7 1.7 0 0 0 1.5-1 1.7 1.7 0 0 0-.3-1.8l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1.7 1.7 0 0 0 1.8.3h.1a1.7 1.7 0 0 0 1-1.5V3a2 2 0 1 1 4 0v.1a1.7 1.7 0 0 0 1 1.5 1.7 1.7 0 0 0 1.8-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.7 1.7 0 0 0-.3 1.8v.1a1.7 1.7 0 0 0 1.5 1H21a2 2 0 1 1 0 4h-.1a1.7 1.7 0 0 0-1.5 1z" />
196
+ `);
197
+ namedIcon("xm-edit-icon", { size: 16, strokeWidth: 1.6 }, () => svg `
198
+ <path d="M12 20h9" />
199
+ <path d="M16.5 3.5a2.121 2.121 0 1 1 3 3L7 19l-4 1 1-4 12.5-12.5z" />
200
+ `);
201
+ namedIcon("xm-paperclip-icon", { size: 14, strokeWidth: 1.8 }, () => svg `
202
+ <path d="M21.4 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 17.93 8.83l-8.06 8.06a2 2 0 0 1-2.83-2.83l7.07-7.07" />
203
+ `);
204
+ namedIcon("xm-send-arrow-icon", { size: 14, strokeWidth: 2 }, () => svg `
205
+ <path d="M7 17L17 7" />
206
+ <path d="M9 7h8v8" />
207
+ `);
208
+ namedIcon("xm-play-icon", { size: 14, strokeWidth: 1.8 }, () => svg `
209
+ <path d="M5 4l14 8-14 8V4z" />
210
+ `);
211
+ namedIcon("xm-file-glyph-icon", { size: 14, strokeWidth: 1.8 }, () => svg `
212
+ <path d="M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8z" />
213
+ <path d="M14 3v5h5" />
214
+ `);
215
+ namedIcon("xm-x-icon", { size: 10, strokeWidth: 2.6 }, () => svg `
216
+ <path d="M6 6l12 12M18 6L6 18" />
217
+ `);
218
+ namedIcon("xm-warn-icon", { size: 14, strokeWidth: 2 }, () => svg `
219
+ <path d="M12 9v4" />
220
+ <path d="M12 17h.01" />
221
+ <path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" />
222
+ `);
223
+ namedIcon("xm-caret-icon", { size: 12, strokeWidth: 2 }, () => svg `
224
+ <polyline points="6 9 12 15 18 9" />
225
+ `);
226
+ /* Chevrons — directional. xm-caret-icon is the canonical chevron-down; these add the other three. */
227
+ namedIcon("xm-chevron-up-icon", { size: 16, strokeWidth: 2 }, () => svg `
228
+ <polyline points="18 15 12 9 6 15" />
229
+ `);
230
+ namedIcon("xm-chevron-down-icon", { size: 16, strokeWidth: 2 }, () => svg `
231
+ <polyline points="6 9 12 15 18 9" />
232
+ `);
233
+ namedIcon("xm-chevron-left-icon", { size: 16, strokeWidth: 2 }, () => svg `
234
+ <polyline points="15 18 9 12 15 6" />
235
+ `);
236
+ namedIcon("xm-chevron-right-icon", { size: 16, strokeWidth: 2 }, () => svg `
237
+ <polyline points="9 18 15 12 9 6" />
238
+ `);
239
+ namedIcon("xm-calendar-icon", { size: 16, strokeWidth: 1.8 }, () => svg `
240
+ <rect x="3" y="4" width="18" height="18" rx="2" />
241
+ <path d="M16 2v4" />
242
+ <path d="M8 2v4" />
243
+ <path d="M3 10h18" />
244
+ `);
245
+ /* Sort indicators — arrow up = ascending, arrow down = descending. */
246
+ namedIcon("xm-sort-asc-icon", { size: 14, strokeWidth: 2 }, () => svg `
247
+ <path d="M12 19V5" />
248
+ <polyline points="6 11 12 5 18 11" />
249
+ `);
250
+ namedIcon("xm-sort-desc-icon", { size: 14, strokeWidth: 2 }, () => svg `
251
+ <path d="M12 5v14" />
252
+ <polyline points="6 13 12 19 18 13" />
253
+ `);
254
+ /* Expand / collapse — diagonal arrows out / in. */
255
+ namedIcon("xm-expand-icon", { size: 16, strokeWidth: 1.8 }, () => svg `
256
+ <polyline points="15 3 21 3 21 9" />
257
+ <polyline points="9 21 3 21 3 15" />
258
+ <path d="M21 3l-7 7" />
259
+ <path d="M3 21l7-7" />
260
+ `);
261
+ namedIcon("xm-collapse-icon", { size: 16, strokeWidth: 1.8 }, () => svg `
262
+ <polyline points="4 14 10 14 10 20" />
263
+ <polyline points="20 10 14 10 14 4" />
264
+ <path d="M14 10l7-7" />
265
+ <path d="M3 21l7-7" />
266
+ `);
267
+ /* Selection marks. The check (xm-check-icon) is the checkbox tick; these add the box, radio dot, and indeterminate bar. */
268
+ namedIcon("xm-checkbox-icon", { size: 16, strokeWidth: 1.8 }, () => svg `
269
+ <rect x="3" y="3" width="18" height="18" rx="3" />
270
+ <polyline points="9 12 11.5 14.5 16 9" />
271
+ `);
272
+ namedIcon("xm-radio-mark-icon", { size: 16, strokeWidth: 1.8 }, () => svg `
273
+ <circle cx="12" cy="12" r="9" />
274
+ <circle cx="12" cy="12" r="3.5" fill="currentColor" stroke="none" />
275
+ `);
276
+ namedIcon("xm-indeterminate-icon", { size: 16, strokeWidth: 2.2 }, () => svg `
277
+ <path d="M6 12h12" />
278
+ `);
279
+ /* Person — identity fallback for avatars when no initials/image. */
280
+ namedIcon("xm-user-icon", { size: 16, strokeWidth: 1.8 }, () => svg `
281
+ <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" />
282
+ <circle cx="12" cy="7" r="4" />
283
+ `);
@@ -0,0 +1,143 @@
1
+ /* ============================================
2
+ Progress — linear + circular, determinate + indeterminate.
3
+
4
+ The indicator (linear fill / circular arc / sweep) is the ONE coral
5
+ accent: var(--md-sys-color-primary). The unfilled track is a neutral
6
+ surface tier that reads on both surface families and both themes
7
+ (AD-1, UX-DR3, AD-13). Progress is display-only chrome — never a
8
+ severity hue.
9
+
10
+ The circular indeterminate spin ALIGNS with primitives' <xm-spinner>
11
+ motion: one rotation source at 0.7s linear infinite (matching
12
+ @keyframes ds-spin). We do NOT introduce a second rotation speed.
13
+
14
+ BEM block: `progress`. Registered in scripts/check-bem.sh STRICT_BLOCKS.
15
+ Elements: __track, __fill, __ring, __ring-svg, __ring-track,
16
+ __ring-indicator, __label. Modifiers: --linear / --circular /
17
+ --indeterminate / --xs / --sm / --md / --lg.
18
+ ============================================ */
19
+
20
+ .progress {
21
+ --progress-color: var(--md-sys-color-primary);
22
+ --progress-track: var(--md-sys-color-surface-container-highest);
23
+ /* Linear track thickness per size (set by the size modifiers). */
24
+ --progress-thickness: 6px;
25
+ /* Circular ring diameter per size. */
26
+ --progress-ring-size: 32px;
27
+ display: inline-flex;
28
+ align-items: center;
29
+ }
30
+
31
+ /* ---------- Size axis ---------- */
32
+ .progress--xs { --progress-thickness: 3px; --progress-ring-size: 18px; }
33
+ .progress--sm { --progress-thickness: 4px; --progress-ring-size: 24px; }
34
+ .progress--md { --progress-thickness: 6px; --progress-ring-size: 32px; }
35
+ .progress--lg { --progress-thickness: 8px; --progress-ring-size: 44px; }
36
+
37
+ /* ---------- Linear ---------- */
38
+ .progress--linear {
39
+ display: block;
40
+ width: 100%;
41
+ }
42
+
43
+ .progress__track {
44
+ display: block;
45
+ position: relative;
46
+ width: 100%;
47
+ height: var(--progress-thickness);
48
+ background: var(--progress-track);
49
+ border-radius: var(--md-sys-shape-corner-full);
50
+ overflow: hidden;
51
+ }
52
+
53
+ .progress__fill {
54
+ display: block;
55
+ height: 100%;
56
+ width: 0;
57
+ background: var(--progress-color);
58
+ border-radius: var(--md-sys-shape-corner-full);
59
+ /* Determinate value changes ease at short4 standard. */
60
+ transition: width var(--md-sys-motion-duration-short4)
61
+ var(--md-sys-motion-easing-standard);
62
+ }
63
+
64
+ /* Linear indeterminate — a fixed-width sweep travelling the track. Opacity /
65
+ translate only; no gradient. */
66
+ .progress--linear.progress--indeterminate .progress__fill {
67
+ width: 40%;
68
+ transition: none;
69
+ animation: progress-sweep var(--md-sys-motion-duration-extra-long2)
70
+ var(--md-sys-motion-easing-standard) infinite;
71
+ }
72
+
73
+ @keyframes progress-sweep {
74
+ from {
75
+ transform: translateX(-110%);
76
+ }
77
+ to {
78
+ transform: translateX(260%);
79
+ }
80
+ }
81
+
82
+ /* ---------- Circular ---------- */
83
+ .progress--circular {
84
+ display: inline-flex;
85
+ }
86
+
87
+ .progress__ring {
88
+ display: inline-flex;
89
+ width: var(--progress-ring-size);
90
+ height: var(--progress-ring-size);
91
+ }
92
+
93
+ .progress__ring-svg {
94
+ width: 100%;
95
+ height: 100%;
96
+ /* Start the determinate arc at 12 o'clock. */
97
+ transform: rotate(-90deg);
98
+ }
99
+
100
+ .progress__ring-track {
101
+ stroke: var(--progress-track);
102
+ }
103
+
104
+ .progress__ring-indicator {
105
+ stroke: var(--progress-color);
106
+ /* Determinate arc grows smoothly at short4 standard. */
107
+ transition: stroke-dashoffset var(--md-sys-motion-duration-short4)
108
+ var(--md-sys-motion-easing-standard);
109
+ }
110
+
111
+ /* Circular indeterminate — rotate the whole svg at the spinner's tempo:
112
+ 0.7s linear infinite (aligned with @keyframes ds-spin). One spin source. */
113
+ .progress--circular.progress--indeterminate .progress__ring-svg {
114
+ transform: none;
115
+ transform-origin: center;
116
+ animation: progress-spin 0.7s linear infinite;
117
+ }
118
+ .progress--circular.progress--indeterminate .progress__ring-indicator {
119
+ transition: none;
120
+ }
121
+
122
+ @keyframes progress-spin {
123
+ to {
124
+ transform: rotate(360deg);
125
+ }
126
+ }
127
+
128
+ /* ---------- Value caption ---------- */
129
+ .progress__label {
130
+ margin-left: var(--s-2);
131
+ font-family: var(--md-sys-typescale-label-medium-font);
132
+ font-size: var(--md-sys-typescale-label-medium-size);
133
+ line-height: var(--md-sys-typescale-label-medium-line-height);
134
+ color: currentColor;
135
+ font-variant-numeric: tabular-nums;
136
+ }
137
+
138
+ @media (prefers-reduced-motion: reduce) {
139
+ .progress--indeterminate .progress__fill,
140
+ .progress--circular.progress--indeterminate .progress__ring-svg {
141
+ animation-duration: var(--md-sys-motion-duration-extra-long4);
142
+ }
143
+ }
@@ -0,0 +1,23 @@
1
+ import { LitElement } from "lit";
2
+ import type { TemplateResult } from "lit";
3
+ export type ProgressVariant = "linear" | "circular";
4
+ export type ProgressSize = "xs" | "sm" | "md" | "lg";
5
+ export declare class XmProgress extends LitElement {
6
+ variant: ProgressVariant;
7
+ value: number;
8
+ indeterminate: boolean;
9
+ size: ProgressSize;
10
+ label: string;
11
+ showLabel: boolean;
12
+ private get _isDeterminate();
13
+ private get _clamped();
14
+ render(): TemplateResult;
15
+ private _renderLinear;
16
+ private _renderCircular;
17
+ private _renderRingIndicator;
18
+ }
19
+ declare global {
20
+ interface HTMLElementTagNameMap {
21
+ "xm-progress": XmProgress;
22
+ }
23
+ }
@@ -0,0 +1,180 @@
1
+ /*
2
+ progress/index.ts — <xm-progress>, linear + circular progress.
3
+
4
+ Two variants × two modes:
5
+ variant="linear" determinate (value 0–100) → a filled track
6
+ indeterminate → an indeterminate sweep
7
+ variant="circular" determinate (value 0–100) → an SVG ring arc
8
+ indeterminate → a rotating ring
9
+
10
+ Omitting/clearing `value` (or setting `indeterminate`) selects indeterminate.
11
+
12
+ The indicator (fill / arc / sweep) is the ONE coral accent —
13
+ `var(--md-sys-color-primary)`; the unfilled track is neutral (AD-1, UX-DR3).
14
+ Progress is display-only; it is NOT severity, so it never uses a status hue.
15
+
16
+ Circular indeterminate ALIGNS with the existing <xm-spinner> motion (AC-3):
17
+ one rotation source — a 0.7s linear infinite spin, matching primitives'
18
+ `@keyframes ds-spin`. We do not invent a second rotation speed.
19
+
20
+ ARIA: role="progressbar" + aria-valuemin/max/now (determinate); indeterminate
21
+ omits aria-valuenow and sets aria-busy + an accessible label.
22
+
23
+ Properties:
24
+ variant "linear" | "circular" (default "linear")
25
+ value number 0–100 — when set (and not `indeterminate`), determinate
26
+ indeterminate boolean — force indeterminate (also inferred from missing value)
27
+ size "xs" | "sm" | "md" | "lg" (default "md")
28
+ label accessible label (used for the aria-label / value caption)
29
+ show-label boolean — render the value as a caption (determinate only)
30
+
31
+ Shadow DOM. Depends only on tokens — no overlay (AD-12). Lit is a bare `import` (peer dep).
32
+ */
33
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
34
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
35
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
36
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
37
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
38
+ };
39
+ import { LitElement, html, svg, nothing } from "lit";
40
+ import { customElement, property } from "lit/decorators.js";
41
+ const PROGRESS_CSS = new URL("../progress/index.css", import.meta.url).href;
42
+ // SVG ring geometry per size — diameter and stroke. The viewBox is fixed at
43
+ // 24×24; the stroke + radius scale within it, and the host CSS sizes the svg.
44
+ const RING_STROKE = {
45
+ xs: 2.5,
46
+ sm: 3,
47
+ md: 3.5,
48
+ lg: 4,
49
+ };
50
+ let XmProgress = class XmProgress extends LitElement {
51
+ constructor() {
52
+ super(...arguments);
53
+ this.variant = "linear";
54
+ this.value = NaN;
55
+ this.indeterminate = false;
56
+ this.size = "md";
57
+ this.label = "";
58
+ this.showLabel = false;
59
+ }
60
+ get _isDeterminate() {
61
+ return !this.indeterminate && Number.isFinite(this.value);
62
+ }
63
+ get _clamped() {
64
+ return Math.max(0, Math.min(100, this.value));
65
+ }
66
+ render() {
67
+ const v = this.variant === "circular" ? "circular" : "linear";
68
+ const sz = ["xs", "sm", "md", "lg"].includes(this.size)
69
+ ? this.size
70
+ : "md";
71
+ const det = this._isDeterminate;
72
+ const cls = `progress progress--${v} progress--${sz}${det ? "" : " progress--indeterminate"}`;
73
+ const aria = det
74
+ ? {
75
+ "aria-valuemin": "0",
76
+ "aria-valuemax": "100",
77
+ "aria-valuenow": String(Math.round(this._clamped)),
78
+ }
79
+ : { "aria-busy": "true" };
80
+ return html `
81
+ <link rel="stylesheet" href="${PROGRESS_CSS}" />
82
+ <style>
83
+ :host { display: inline-flex; }
84
+ :host([variant="linear"]) { display: block; }
85
+ :host([hidden]) { display: none; }
86
+ </style>
87
+ <div
88
+ class="${cls}"
89
+ role="progressbar"
90
+ aria-label=${this.label || (det ? nothing : "Loading")}
91
+ aria-valuemin=${aria["aria-valuemin"] ?? nothing}
92
+ aria-valuemax=${aria["aria-valuemax"] ?? nothing}
93
+ aria-valuenow=${aria["aria-valuenow"] ?? nothing}
94
+ aria-busy=${aria["aria-busy"] ?? nothing}
95
+ >
96
+ ${v === "linear" ? this._renderLinear(det) : this._renderCircular(det, sz)}
97
+ </div>
98
+ ${this.showLabel && det
99
+ ? html `<span class="progress__label">${Math.round(this._clamped)}%</span>`
100
+ : nothing}
101
+ `;
102
+ }
103
+ _renderLinear(det) {
104
+ const fillStyle = det ? `width:${this._clamped}%;` : "";
105
+ return html `
106
+ <span class="progress__track">
107
+ <span class="progress__fill" style=${fillStyle}></span>
108
+ </span>
109
+ `;
110
+ }
111
+ _renderCircular(det, sz) {
112
+ const stroke = RING_STROKE[sz];
113
+ const r = 12 - stroke; // viewBox 24×24, centered at 12,12
114
+ const circumference = 2 * Math.PI * r;
115
+ return html `
116
+ <span class="progress__ring">
117
+ ${svg `
118
+ <svg viewBox="0 0 24 24" class="progress__ring-svg" aria-hidden="true">
119
+ <circle
120
+ class="progress__ring-track"
121
+ cx="12" cy="12" r="${r}"
122
+ fill="none" stroke-width="${stroke}"
123
+ />
124
+ ${this._renderRingIndicator(det, r, circumference, stroke)}
125
+ </svg>
126
+ `}
127
+ </span>
128
+ `;
129
+ }
130
+ _renderRingIndicator(det, r, circumference, stroke) {
131
+ if (det) {
132
+ const offset = circumference * (1 - this._clamped / 100);
133
+ return svg `
134
+ <circle
135
+ class="progress__ring-indicator"
136
+ cx="12" cy="12" r="${r}"
137
+ fill="none" stroke-width="${stroke}"
138
+ stroke-linecap="round"
139
+ stroke-dasharray="${circumference}"
140
+ stroke-dashoffset="${offset}"
141
+ />
142
+ `;
143
+ }
144
+ // Indeterminate: a short fixed arc, rotated by the spin animation in CSS
145
+ // (aligned with ds-spin — 0.7s linear infinite). The arc spans ~25% of the
146
+ // ring; the whole svg rotates.
147
+ const arc = circumference * 0.25;
148
+ return svg `
149
+ <circle
150
+ class="progress__ring-indicator"
151
+ cx="12" cy="12" r="${r}"
152
+ fill="none" stroke-width="${stroke}"
153
+ stroke-linecap="round"
154
+ stroke-dasharray="${arc} ${circumference - arc}"
155
+ />
156
+ `;
157
+ }
158
+ };
159
+ __decorate([
160
+ property({ type: String })
161
+ ], XmProgress.prototype, "variant", void 0);
162
+ __decorate([
163
+ property({ type: Number })
164
+ ], XmProgress.prototype, "value", void 0);
165
+ __decorate([
166
+ property({ type: Boolean })
167
+ ], XmProgress.prototype, "indeterminate", void 0);
168
+ __decorate([
169
+ property({ type: String })
170
+ ], XmProgress.prototype, "size", void 0);
171
+ __decorate([
172
+ property({ type: String })
173
+ ], XmProgress.prototype, "label", void 0);
174
+ __decorate([
175
+ property({ type: Boolean, attribute: "show-label" })
176
+ ], XmProgress.prototype, "showLabel", void 0);
177
+ XmProgress = __decorate([
178
+ customElement("xm-progress")
179
+ ], XmProgress);
180
+ export { XmProgress };