@robr0/design-system 0.6.0 → 0.8.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 (48) hide show
  1. package/LICENSE +53 -2
  2. package/README.md +36 -5
  3. package/components/AgentPlan/AgentPlan.css +231 -0
  4. package/components/AgentPlan/AgentPlan.d.ts +41 -0
  5. package/components/AgentPlan/AgentPlan.js +99 -0
  6. package/components/AgentStatus/AgentStatus.css +26 -11
  7. package/components/Card/Card.css +9 -0
  8. package/components/Card/Card.d.ts +6 -0
  9. package/components/Card/Card.js +2 -1
  10. package/components/Composer/Composer.css +18 -0
  11. package/components/Composer/Composer.d.ts +3 -0
  12. package/components/Composer/Composer.js +12 -1
  13. package/components/DataTable/DataTable.css +105 -0
  14. package/components/DataTable/DataTable.d.ts +81 -0
  15. package/components/DataTable/DataTable.js +235 -0
  16. package/components/EventCalendar/EventCalendar.css +328 -0
  17. package/components/EventCalendar/EventCalendar.d.ts +51 -0
  18. package/components/EventCalendar/EventCalendar.js +213 -0
  19. package/components/ModelPicker/ModelPicker.css +238 -0
  20. package/components/ModelPicker/ModelPicker.d.ts +60 -0
  21. package/components/ModelPicker/ModelPicker.js +217 -0
  22. package/components/NotificationCenter/NotificationCenter.css +262 -0
  23. package/components/NotificationCenter/NotificationCenter.d.ts +72 -0
  24. package/components/NotificationCenter/NotificationCenter.js +128 -0
  25. package/components/Prose/Prose.css +18 -1
  26. package/components/Reasoning/Reasoning.css +19 -4
  27. package/components/ShaderField/ShaderField.css +24 -0
  28. package/components/ShaderField/ShaderField.d.ts +68 -0
  29. package/components/ShaderField/ShaderField.js +54 -0
  30. package/components/ShaderField/field.glsl.d.ts +39 -0
  31. package/components/ShaderField/field.glsl.js +178 -0
  32. package/components/ShaderField/useShaderField.d.ts +103 -0
  33. package/components/ShaderField/useShaderField.js +409 -0
  34. package/components/Timeline/Timeline.css +17 -0
  35. package/components/Timeline/Timeline.d.ts +2 -0
  36. package/components/Timeline/Timeline.js +1 -0
  37. package/components/registry.json +48 -0
  38. package/components/registry.json.d.ts +48 -0
  39. package/components/registry.json.js +1 -1
  40. package/index.d.ts +6 -0
  41. package/index.js +19 -0
  42. package/package.json +5 -1
  43. package/tokens/registry.json +1 -0
  44. package/tokens/registry.json.d.ts +1 -0
  45. package/tokens/registry.json.js +1 -1
  46. package/tokens/tokens-dark.css +1 -1
  47. package/tokens/tokens-light.css +2 -2
  48. package/tokens/tokens-motion.css +2 -0
@@ -0,0 +1,409 @@
1
+ import { useState, useRef, useEffect } from "react";
2
+ import { BLOB_COUNT, vertexSource, fragmentSource } from "./field.glsl.js";
3
+ const DEFAULT_SHADER_PARAMS = {
4
+ intensity: 0.5,
5
+ warp: 0.14,
6
+ scale: 2.7,
7
+ speed: 2,
8
+ grain: 0.1,
9
+ streak: 0.4,
10
+ react: 0,
11
+ crop: 0.5
12
+ };
13
+ const DEFAULT_SHADER_BLOBS = [
14
+ { token: "--color-core-accent-gold", size: 0.45, cx: 0.175, cy: 0.125, period: 18, phase: 0, weight: 1 },
15
+ { token: "--color-core-accent-mint", size: 0.55, cx: 0.125, cy: 0.125, period: 16, phase: 1, weight: 1 },
16
+ { token: "--color-core-accent-violet", size: 0.9, cx: 0.35, cy: 0.25, period: 22, phase: 0.5, weight: 1 },
17
+ { token: "--color-bg-container-secondary", size: 0.55, cx: 0.025, cy: 0.075, period: 14, phase: 1.5, weight: 1 },
18
+ { token: "--color-core-accent-cobalt", size: 0.55, cx: -0.125, cy: 0.475, period: 17, phase: 0.8, weight: 1 },
19
+ { token: "--color-core-accent-coral", size: 0.48, cx: 0.39, cy: -0.26, period: 19, phase: 0.3, weight: 1 },
20
+ { token: "--color-core-accent-amber", size: 0.3, cx: 0.35, cy: 0.3, period: 15, phase: 1.2, weight: 1 },
21
+ { token: "--color-core-ui-secondary", size: 0.75, cx: -0.125, cy: -0.025, period: 20, phase: 0.7, weight: 1 }
22
+ ];
23
+ const RENDER_SCALE = 0.5;
24
+ const REFERENCE_WIDTH = 1440;
25
+ function fieldUnit(cssWidth, crop) {
26
+ if (cssWidth <= 0) return 1;
27
+ return cssWidth * Math.pow(Math.max(REFERENCE_WIDTH / cssWidth, 1), crop);
28
+ }
29
+ const FRAME_MS = 1e3 / 30;
30
+ const FRAME_MS_ACTIVE = 1e3 / 60;
31
+ const WAKE_IDLE = 0.015;
32
+ const COLOR_FADE_MS = 300;
33
+ function parseColor(value) {
34
+ const v = value.trim();
35
+ const hex = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(v);
36
+ if (hex) {
37
+ const h = hex[1];
38
+ const full = h.length === 3 ? h.split("").map((c) => c + c).join("") : h;
39
+ return [
40
+ parseInt(full.slice(0, 2), 16) / 255,
41
+ parseInt(full.slice(2, 4), 16) / 255,
42
+ parseInt(full.slice(4, 6), 16) / 255
43
+ ];
44
+ }
45
+ const rgb = /^rgba?\(\s*(\d+)[,\s]+(\d+)[,\s]+(\d+)/.exec(v);
46
+ if (rgb) {
47
+ return [Number(rgb[1]) / 255, Number(rgb[2]) / 255, Number(rgb[3]) / 255];
48
+ }
49
+ return null;
50
+ }
51
+ function srgbToLinear(c) {
52
+ return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
53
+ }
54
+ function compile(gl, type, source) {
55
+ const shader = gl.createShader(type);
56
+ if (!shader) return null;
57
+ gl.shaderSource(shader, source);
58
+ gl.compileShader(shader);
59
+ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
60
+ console.error("ShaderField compile error:", gl.getShaderInfoLog(shader));
61
+ gl.deleteShader(shader);
62
+ return null;
63
+ }
64
+ return shader;
65
+ }
66
+ function useShaderField(canvasRef, params, enabled = true) {
67
+ const [supported, setSupported] = useState(true);
68
+ const [active, setActive] = useState(false);
69
+ const paramsRef = useRef(params);
70
+ const redrawRef = useRef(() => {
71
+ });
72
+ useEffect(() => {
73
+ paramsRef.current = params;
74
+ redrawRef.current();
75
+ }, [params]);
76
+ useEffect(() => {
77
+ const canvas = canvasRef.current;
78
+ if (!canvas || !enabled) return;
79
+ const gl = canvas.getContext("webgl2", {
80
+ alpha: true,
81
+ antialias: false,
82
+ depth: false,
83
+ stencil: false,
84
+ premultipliedAlpha: true,
85
+ powerPreference: "low-power"
86
+ });
87
+ if (!gl) {
88
+ setSupported(false);
89
+ return;
90
+ }
91
+ if (!gl.isContextLost()) {
92
+ canvas.__dsLoseExt = gl.getExtension("WEBGL_lose_context");
93
+ }
94
+ const loseExt = () => gl.getExtension("WEBGL_lose_context") ?? canvas.__dsLoseExt ?? null;
95
+ let program = null;
96
+ let vao = null;
97
+ let loc = {};
98
+ function initGL() {
99
+ if (!gl) return false;
100
+ const vs = compile(gl, gl.VERTEX_SHADER, vertexSource);
101
+ const fs = compile(gl, gl.FRAGMENT_SHADER, fragmentSource);
102
+ if (!vs || !fs) return false;
103
+ program = gl.createProgram();
104
+ if (!program) return false;
105
+ gl.attachShader(program, vs);
106
+ gl.attachShader(program, fs);
107
+ gl.linkProgram(program);
108
+ gl.deleteShader(vs);
109
+ gl.deleteShader(fs);
110
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
111
+ console.error("ShaderField link error:", gl.getProgramInfoLog(program));
112
+ return false;
113
+ }
114
+ gl.useProgram(program);
115
+ vao = gl.createVertexArray();
116
+ gl.bindVertexArray(vao);
117
+ gl.disable(gl.BLEND);
118
+ gl.disable(gl.DEPTH_TEST);
119
+ loc = {};
120
+ for (const name of [
121
+ "u_resolution",
122
+ "u_unit",
123
+ "u_time",
124
+ "u_color[0]",
125
+ "u_blob[0]",
126
+ "u_motion[0]",
127
+ "u_intensity",
128
+ "u_warp",
129
+ "u_scale",
130
+ "u_grain",
131
+ "u_streak",
132
+ "u_mouse",
133
+ "u_mvel",
134
+ "u_react"
135
+ ]) {
136
+ loc[name] = gl.getUniformLocation(program, name);
137
+ }
138
+ return true;
139
+ }
140
+ let uploadedBlobs = null;
141
+ function uploadBlobs(blobs) {
142
+ if (!gl) return;
143
+ const blob = new Float32Array(BLOB_COUNT * 4);
144
+ const motion = new Float32Array(BLOB_COUNT * 4);
145
+ for (let i = 0; i < BLOB_COUNT; i++) {
146
+ const b = blobs[i];
147
+ if (!b) {
148
+ blob[i * 4 + 0] = 99;
149
+ blob[i * 4 + 1] = 99;
150
+ blob[i * 4 + 2] = 0.01;
151
+ continue;
152
+ }
153
+ blob[i * 4 + 0] = b.cx;
154
+ blob[i * 4 + 1] = b.cy;
155
+ blob[i * 4 + 2] = b.size * 0.42;
156
+ blob[i * 4 + 3] = b.weight;
157
+ const wx = 2 * Math.PI / b.period;
158
+ motion[i * 4 + 0] = wx;
159
+ motion[i * 4 + 1] = wx * 0.83;
160
+ motion[i * 4 + 2] = b.phase * 2.1;
161
+ motion[i * 4 + 3] = b.phase * 3.7;
162
+ }
163
+ gl.uniform4fv(loc["u_blob[0]"], blob);
164
+ gl.uniform4fv(loc["u_motion[0]"], motion);
165
+ uploadedBlobs = blobs;
166
+ }
167
+ const colorCurrent = new Float32Array(BLOB_COUNT * 3);
168
+ const colorTarget = new Float32Array(BLOB_COUNT * 3);
169
+ let colorFadeT = COLOR_FADE_MS;
170
+ function readColors(into) {
171
+ const style = getComputedStyle(canvas);
172
+ into.fill(0);
173
+ paramsRef.current.blobs.slice(0, BLOB_COUNT).forEach((b, i) => {
174
+ const parsed = parseColor(style.getPropertyValue(b.token));
175
+ if (parsed) {
176
+ into[i * 3 + 0] = srgbToLinear(parsed[0]);
177
+ into[i * 3 + 1] = srgbToLinear(parsed[1]);
178
+ into[i * 3 + 2] = srgbToLinear(parsed[2]);
179
+ }
180
+ });
181
+ }
182
+ readColors(colorCurrent);
183
+ colorTarget.set(colorCurrent);
184
+ let bufWidth = 0;
185
+ let bufHeight = 0;
186
+ let cssWidth = 0;
187
+ function resize() {
188
+ if (!gl) return;
189
+ const c = canvas;
190
+ const dpr = window.devicePixelRatio || 1;
191
+ cssWidth = c.clientWidth;
192
+ const w = Math.max(1, Math.round(c.clientWidth * dpr * RENDER_SCALE));
193
+ const h = Math.max(1, Math.round(c.clientHeight * dpr * RENDER_SCALE));
194
+ if (w === bufWidth && h === bufHeight) return;
195
+ bufWidth = w;
196
+ bufHeight = h;
197
+ c.width = w;
198
+ c.height = h;
199
+ gl.viewport(0, 0, w, h);
200
+ gl.uniform2f(loc["u_resolution"], w, h);
201
+ }
202
+ let fieldTime = 0;
203
+ let colorsDirty = false;
204
+ const mouseTarget = { x: 9, y: 9 };
205
+ const mouse = { x: 9, y: 9 };
206
+ let mouseVel = 0;
207
+ let moveAccum = 0;
208
+ const onPointerMove = (e) => {
209
+ const c = canvas;
210
+ const rect = c.getBoundingClientRect();
211
+ if (rect.width === 0) return;
212
+ const unit = fieldUnit(rect.width, paramsRef.current.crop);
213
+ const x = (e.clientX - rect.left - rect.width / 2) / unit;
214
+ const y = (e.clientY - rect.top - rect.height / 2) / unit;
215
+ if (mouseTarget.x < 5) {
216
+ moveAccum += Math.hypot(x - mouseTarget.x, y - mouseTarget.y);
217
+ }
218
+ mouseTarget.x = x;
219
+ mouseTarget.y = y;
220
+ if (mouse.x > 5) {
221
+ mouse.x = x;
222
+ mouse.y = y;
223
+ }
224
+ };
225
+ window.addEventListener("pointermove", onPointerMove, { passive: true });
226
+ function draw(dtMs) {
227
+ if (!gl || !program) return;
228
+ resize();
229
+ if (paramsRef.current.blobs !== uploadedBlobs) {
230
+ uploadBlobs(paramsRef.current.blobs);
231
+ colorsDirty = true;
232
+ }
233
+ if (colorsDirty) {
234
+ readColors(colorTarget);
235
+ colorFadeT = 0;
236
+ colorsDirty = false;
237
+ }
238
+ if (colorFadeT < COLOR_FADE_MS) {
239
+ colorFadeT = Math.min(colorFadeT + dtMs, COLOR_FADE_MS);
240
+ const t = colorFadeT / COLOR_FADE_MS;
241
+ for (let i = 0; i < colorCurrent.length; i++) {
242
+ colorCurrent[i] += (colorTarget[i] - colorCurrent[i]) * t;
243
+ }
244
+ }
245
+ const p = paramsRef.current;
246
+ gl.uniform3fv(loc["u_color[0]"], colorCurrent);
247
+ gl.uniform1f(
248
+ loc["u_unit"],
249
+ bufWidth * (fieldUnit(cssWidth, p.crop) / Math.max(cssWidth, 1))
250
+ );
251
+ gl.uniform1f(loc["u_time"], fieldTime);
252
+ gl.uniform1f(loc["u_intensity"], p.intensity);
253
+ gl.uniform1f(loc["u_warp"], p.warp);
254
+ gl.uniform1f(loc["u_scale"], p.scale);
255
+ gl.uniform1f(loc["u_grain"], p.grain);
256
+ gl.uniform1f(loc["u_streak"], p.streak);
257
+ const dtSec = Math.max(dtMs / 1e3, 1e-3);
258
+ const k = 1 - Math.exp(-dtSec * 14);
259
+ mouse.x += (mouseTarget.x - mouse.x) * k;
260
+ mouse.y += (mouseTarget.y - mouse.y) * k;
261
+ const instant = moveAccum / dtSec;
262
+ moveAccum = 0;
263
+ const blend = 1 - Math.exp(-dtSec * (instant > mouseVel ? 14 : 2.2));
264
+ mouseVel += (instant - mouseVel) * blend;
265
+ gl.uniform2f(loc["u_mouse"], mouse.x, mouse.y);
266
+ gl.uniform1f(loc["u_mvel"], mouseVel);
267
+ gl.uniform1f(loc["u_react"], p.react);
268
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
269
+ frameBudget = mouseVel > WAKE_IDLE && p.react > 0 ? FRAME_MS_ACTIVE : FRAME_MS;
270
+ }
271
+ let raf = 0;
272
+ let lastDraw = 0;
273
+ let running = false;
274
+ let disposed = false;
275
+ let frameBudget = FRAME_MS;
276
+ const reduceQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
277
+ function frame(now) {
278
+ raf = requestAnimationFrame(frame);
279
+ const elapsed = now - lastDraw;
280
+ if (elapsed < frameBudget - 1) return;
281
+ const dt = Math.min(elapsed, 100);
282
+ lastDraw = now;
283
+ fieldTime += dt / 1e3 * paramsRef.current.speed;
284
+ draw(dt);
285
+ }
286
+ function start() {
287
+ if (running || disposed || reduceQuery.matches || document.hidden) return;
288
+ running = true;
289
+ lastDraw = performance.now();
290
+ raf = requestAnimationFrame(frame);
291
+ }
292
+ function stop() {
293
+ running = false;
294
+ cancelAnimationFrame(raf);
295
+ }
296
+ function renderOnce() {
297
+ if (disposed || running) return;
298
+ draw(COLOR_FADE_MS);
299
+ }
300
+ redrawRef.current = renderOnce;
301
+ const onReduceChange = () => {
302
+ if (reduceQuery.matches) {
303
+ stop();
304
+ renderOnce();
305
+ } else {
306
+ start();
307
+ }
308
+ };
309
+ reduceQuery.addEventListener("change", onReduceChange);
310
+ const onVisibility = () => {
311
+ if (document.hidden) stop();
312
+ else start();
313
+ };
314
+ document.addEventListener("visibilitychange", onVisibility);
315
+ const themeObserver = new MutationObserver(() => {
316
+ colorsDirty = true;
317
+ if (!running) {
318
+ readColors(colorTarget);
319
+ colorCurrent.set(colorTarget);
320
+ colorsDirty = false;
321
+ renderOnce();
322
+ }
323
+ });
324
+ themeObserver.observe(document.documentElement, {
325
+ attributes: true,
326
+ attributeFilter: ["data-theme", "style"]
327
+ });
328
+ const resizeObserver = new ResizeObserver(() => {
329
+ if (!running) {
330
+ renderOnce();
331
+ }
332
+ });
333
+ resizeObserver.observe(canvas);
334
+ let restoreTimer = 0;
335
+ const onContextLost = (e) => {
336
+ e.preventDefault();
337
+ stop();
338
+ setActive(false);
339
+ window.clearTimeout(restoreTimer);
340
+ restoreTimer = window.setTimeout(() => {
341
+ if (disposed || !gl.isContextLost()) return;
342
+ try {
343
+ loseExt()?.restoreContext();
344
+ } catch {
345
+ setSupported(false);
346
+ }
347
+ }, 700);
348
+ };
349
+ const onContextRestored = () => {
350
+ if (initGL()) {
351
+ bufWidth = 0;
352
+ bufHeight = 0;
353
+ uploadedBlobs = null;
354
+ colorsDirty = true;
355
+ setActive(true);
356
+ if (reduceQuery.matches) renderOnce();
357
+ else start();
358
+ }
359
+ };
360
+ canvas.addEventListener("webglcontextlost", onContextLost);
361
+ canvas.addEventListener("webglcontextrestored", onContextRestored);
362
+ if (gl.isContextLost()) {
363
+ const ext = loseExt();
364
+ if (!ext) {
365
+ queueMicrotask(() => setSupported(false));
366
+ } else {
367
+ try {
368
+ ext.restoreContext();
369
+ } catch {
370
+ queueMicrotask(() => setSupported(false));
371
+ }
372
+ }
373
+ } else if (initGL()) {
374
+ draw(COLOR_FADE_MS);
375
+ setActive(true);
376
+ start();
377
+ } else {
378
+ setSupported(false);
379
+ }
380
+ return () => {
381
+ disposed = true;
382
+ stop();
383
+ window.clearTimeout(restoreTimer);
384
+ redrawRef.current = () => {
385
+ };
386
+ window.removeEventListener("pointermove", onPointerMove);
387
+ reduceQuery.removeEventListener("change", onReduceChange);
388
+ document.removeEventListener("visibilitychange", onVisibility);
389
+ themeObserver.disconnect();
390
+ resizeObserver.disconnect();
391
+ canvas.removeEventListener("webglcontextlost", onContextLost);
392
+ canvas.removeEventListener("webglcontextrestored", onContextRestored);
393
+ if (program) gl.deleteProgram(program);
394
+ if (vao) gl.deleteVertexArray(vao);
395
+ try {
396
+ if (!gl.isContextLost()) loseExt()?.loseContext();
397
+ } catch {
398
+ }
399
+ };
400
+ }, [canvasRef, enabled]);
401
+ return { supported, active };
402
+ }
403
+ export {
404
+ DEFAULT_SHADER_BLOBS,
405
+ DEFAULT_SHADER_PARAMS,
406
+ parseColor,
407
+ srgbToLinear,
408
+ useShaderField
409
+ };
@@ -286,6 +286,23 @@
286
286
  color: var(--color-status-positive-text);
287
287
  }
288
288
 
289
+ .ds-timeline__role-subtitle {
290
+ margin: 0;
291
+ font-family: var(--font-paragraph-family);
292
+ font-size: var(--font-paragraph-size);
293
+ font-weight: var(--font-paragraph-weight);
294
+ line-height: var(--font-paragraph-line-height);
295
+ letter-spacing: var(--font-paragraph-letter-spacing);
296
+ color: var(--color-text-secondary);
297
+ }
298
+
299
+ /* The title and its subtitle read as one header block, so whatever follows
300
+ needs a wider break than the role's own 8px rhythm to separate from it. */
301
+ .ds-timeline__role-subtitle + .ds-timeline__role-description,
302
+ .ds-timeline__role-subtitle + .ds-timeline__role-bullets {
303
+ margin-top: var(--gap-sm);
304
+ }
305
+
289
306
  .ds-timeline__role-description {
290
307
  margin: 0;
291
308
  font-family: var(--font-paragraph-family);
@@ -13,6 +13,8 @@ export interface TimelineItem {
13
13
  export interface TimelineRole {
14
14
  /** Role or position title */
15
15
  title: string;
16
+ /** Secondary line under the title, e.g. the team, org, or product the role sat in */
17
+ subtitle?: React.ReactNode;
16
18
  /** Start of the date range, e.g. "May 2024" (omit for entries with no dates) */
17
19
  start?: string;
18
20
  /** End of the date range, e.g. "Jan 2026" (ignored when `present` is set) */
@@ -23,6 +23,7 @@ const CompanyTimeline = ({ items, className = "" }) => {
23
23
  /* @__PURE__ */ jsx("h3", { className: `${BASE_CLASS}__role-title`, children: role.title }),
24
24
  renderRoleDates(role)
25
25
  ] }),
26
+ role.subtitle && /* @__PURE__ */ jsx("p", { className: `${BASE_CLASS}__role-subtitle`, children: role.subtitle }),
26
27
  role.description && /* @__PURE__ */ jsx("p", { className: `${BASE_CLASS}__role-description`, children: role.description }),
27
28
  role.bullets && role.bullets.length > 0 && /* @__PURE__ */ jsx("ul", { className: `${BASE_CLASS}__role-bullets`, children: role.bullets.map((bullet, bulletIndex) => /* @__PURE__ */ jsx("li", { children: bullet }, bulletIndex)) })
28
29
  ] }, `${role.title}-${roleIndex}`)) })
@@ -20,6 +20,14 @@
20
20
  "category": "data-display",
21
21
  "client": true
22
22
  },
23
+ {
24
+ "name": "AgentPlan",
25
+ "label": "Agent plan",
26
+ "slug": "agent-plan",
27
+ "description": "A collapsible checklist of an agent's task, with live step states and a progress readout.",
28
+ "category": "ai",
29
+ "client": true
30
+ },
23
31
  {
24
32
  "name": "AgentStatus",
25
33
  "label": "Agent status",
@@ -252,6 +260,14 @@
252
260
  "category": "charts",
253
261
  "client": false
254
262
  },
263
+ {
264
+ "name": "DataTable",
265
+ "label": "Data table",
266
+ "slug": "data-table",
267
+ "description": "The wired table: sorting, search, row selection, and pagination assembled around Table.",
268
+ "category": "data-display",
269
+ "client": true
270
+ },
255
271
  {
256
272
  "name": "DateInput",
257
273
  "label": "Date input",
@@ -332,6 +348,14 @@
332
348
  "category": "data-display",
333
349
  "client": false
334
350
  },
351
+ {
352
+ "name": "EventCalendar",
353
+ "label": "Event calendar",
354
+ "slug": "event-calendar",
355
+ "description": "A month grid with event pills, overflow counts, and month navigation.",
356
+ "category": "data-display",
357
+ "client": true
358
+ },
335
359
  {
336
360
  "name": "Field",
337
361
  "label": "Field",
@@ -412,6 +436,14 @@
412
436
  "category": "ai",
413
437
  "client": false
414
438
  },
439
+ {
440
+ "name": "ModelPicker",
441
+ "label": "Model picker",
442
+ "slug": "model-picker",
443
+ "description": "A model selector for chat surfaces, with per-model descriptions and an optional effort row.",
444
+ "category": "ai",
445
+ "client": true
446
+ },
415
447
  {
416
448
  "name": "Nav",
417
449
  "label": "Navigation",
@@ -428,6 +460,14 @@
428
460
  "category": "navigation",
429
461
  "client": true
430
462
  },
463
+ {
464
+ "name": "NotificationCenter",
465
+ "label": "Notification centre",
466
+ "slug": "notification-center",
467
+ "description": "A persistent notification inbox with unread count, filter tabs, and per-item actions.",
468
+ "category": "feedback",
469
+ "client": true
470
+ },
431
471
  {
432
472
  "name": "Pagination",
433
473
  "label": "Pagination",
@@ -516,6 +556,14 @@
516
556
  "category": "data-display",
517
557
  "client": true
518
558
  },
559
+ {
560
+ "name": "ShaderField",
561
+ "label": "Shader field",
562
+ "slug": "shader-field",
563
+ "description": "An ambient WebGL2 field of soft light sources that sample colour tokens, with a reported fallback status.",
564
+ "category": "layout",
565
+ "client": true
566
+ },
519
567
  {
520
568
  "name": "Skeleton",
521
569
  "label": "Skeleton",
@@ -20,6 +20,14 @@ declare const _default: {
20
20
  "category": "data-display",
21
21
  "client": true
22
22
  },
23
+ {
24
+ "name": "AgentPlan",
25
+ "label": "Agent plan",
26
+ "slug": "agent-plan",
27
+ "description": "A collapsible checklist of an agent's task, with live step states and a progress readout.",
28
+ "category": "ai",
29
+ "client": true
30
+ },
23
31
  {
24
32
  "name": "AgentStatus",
25
33
  "label": "Agent status",
@@ -252,6 +260,14 @@ declare const _default: {
252
260
  "category": "charts",
253
261
  "client": false
254
262
  },
263
+ {
264
+ "name": "DataTable",
265
+ "label": "Data table",
266
+ "slug": "data-table",
267
+ "description": "The wired table: sorting, search, row selection, and pagination assembled around Table.",
268
+ "category": "data-display",
269
+ "client": true
270
+ },
255
271
  {
256
272
  "name": "DateInput",
257
273
  "label": "Date input",
@@ -332,6 +348,14 @@ declare const _default: {
332
348
  "category": "data-display",
333
349
  "client": false
334
350
  },
351
+ {
352
+ "name": "EventCalendar",
353
+ "label": "Event calendar",
354
+ "slug": "event-calendar",
355
+ "description": "A month grid with event pills, overflow counts, and month navigation.",
356
+ "category": "data-display",
357
+ "client": true
358
+ },
335
359
  {
336
360
  "name": "Field",
337
361
  "label": "Field",
@@ -412,6 +436,14 @@ declare const _default: {
412
436
  "category": "ai",
413
437
  "client": false
414
438
  },
439
+ {
440
+ "name": "ModelPicker",
441
+ "label": "Model picker",
442
+ "slug": "model-picker",
443
+ "description": "A model selector for chat surfaces, with per-model descriptions and an optional effort row.",
444
+ "category": "ai",
445
+ "client": true
446
+ },
415
447
  {
416
448
  "name": "Nav",
417
449
  "label": "Navigation",
@@ -428,6 +460,14 @@ declare const _default: {
428
460
  "category": "navigation",
429
461
  "client": true
430
462
  },
463
+ {
464
+ "name": "NotificationCenter",
465
+ "label": "Notification centre",
466
+ "slug": "notification-center",
467
+ "description": "A persistent notification inbox with unread count, filter tabs, and per-item actions.",
468
+ "category": "feedback",
469
+ "client": true
470
+ },
431
471
  {
432
472
  "name": "Pagination",
433
473
  "label": "Pagination",
@@ -516,6 +556,14 @@ declare const _default: {
516
556
  "category": "data-display",
517
557
  "client": true
518
558
  },
559
+ {
560
+ "name": "ShaderField",
561
+ "label": "Shader field",
562
+ "slug": "shader-field",
563
+ "description": "An ambient WebGL2 field of soft light sources that sample colour tokens, with a reported fallback status.",
564
+ "category": "layout",
565
+ "client": true
566
+ },
519
567
  {
520
568
  "name": "Skeleton",
521
569
  "label": "Skeleton",