@atelier-ui/react 0.2.14 → 0.2.15

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 (98) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/package.json +1 -1
  3. package/src/lib/accordion/atl-accordion.css +21 -5
  4. package/src/lib/accordion/atl-accordion.d.ts.map +1 -1
  5. package/src/lib/accordion/atl-accordion.js +2 -3
  6. package/src/lib/accordion/atl-accordion.js.map +1 -1
  7. package/src/lib/alert/atl-alert.css +11 -1
  8. package/src/lib/alert/atl-alert.d.ts.map +1 -1
  9. package/src/lib/alert/atl-alert.js +2 -1
  10. package/src/lib/alert/atl-alert.js.map +1 -1
  11. package/src/lib/avatar/atl-avatar.css +19 -3
  12. package/src/lib/avatar/atl-avatar.d.ts.map +1 -1
  13. package/src/lib/avatar/atl-avatar.js +2 -1
  14. package/src/lib/avatar/atl-avatar.js.map +1 -1
  15. package/src/lib/badge/atl-badge.css +16 -6
  16. package/src/lib/breadcrumbs/atl-breadcrumbs.css +16 -0
  17. package/src/lib/button/atl-button.css +12 -2
  18. package/src/lib/card/atl-card.css +24 -4
  19. package/src/lib/chat/atl-chat.css +37 -11
  20. package/src/lib/chat/atl-chat.d.ts.map +1 -1
  21. package/src/lib/chat/atl-chat.js +2 -1
  22. package/src/lib/chat/atl-chat.js.map +1 -1
  23. package/src/lib/checkbox/atl-checkbox.css +12 -2
  24. package/src/lib/checkbox/atl-checkbox.d.ts +1 -5
  25. package/src/lib/checkbox/atl-checkbox.d.ts.map +1 -1
  26. package/src/lib/checkbox/atl-checkbox.js +2 -3
  27. package/src/lib/checkbox/atl-checkbox.js.map +1 -1
  28. package/src/lib/code-block/atl-code-block.css +25 -6
  29. package/src/lib/code-block/atl-code-block.d.ts.map +1 -1
  30. package/src/lib/code-block/atl-code-block.js +2 -1
  31. package/src/lib/code-block/atl-code-block.js.map +1 -1
  32. package/src/lib/combobox/atl-combobox.css +56 -5
  33. package/src/lib/combobox/atl-combobox.d.ts.map +1 -1
  34. package/src/lib/combobox/atl-combobox.js +4 -2
  35. package/src/lib/combobox/atl-combobox.js.map +1 -1
  36. package/src/lib/dialog/atl-dialog.css +24 -4
  37. package/src/lib/dialog/atl-dialog.d.ts.map +1 -1
  38. package/src/lib/dialog/atl-dialog.js +2 -1
  39. package/src/lib/dialog/atl-dialog.js.map +1 -1
  40. package/src/lib/drawer/atl-drawer.css +24 -4
  41. package/src/lib/drawer/atl-drawer.d.ts.map +1 -1
  42. package/src/lib/drawer/atl-drawer.js +2 -1
  43. package/src/lib/drawer/atl-drawer.js.map +1 -1
  44. package/src/lib/icon/atl-icon.css +18 -0
  45. package/src/lib/icon/atl-icon.d.ts +2 -1
  46. package/src/lib/icon/atl-icon.d.ts.map +1 -1
  47. package/src/lib/icon/atl-icon.js +6 -25
  48. package/src/lib/icon/atl-icon.js.map +1 -1
  49. package/src/lib/icons.d.ts +39 -0
  50. package/src/lib/icons.d.ts.map +1 -0
  51. package/src/lib/icons.js +49 -0
  52. package/src/lib/icons.js.map +1 -0
  53. package/src/lib/input/atl-input.css +21 -7
  54. package/src/lib/input/atl-input.d.ts.map +1 -1
  55. package/src/lib/input/atl-input.js +2 -1
  56. package/src/lib/input/atl-input.js.map +1 -1
  57. package/src/lib/menu/atl-menu.css +28 -3
  58. package/src/lib/pagination/atl-pagination.css +11 -1
  59. package/src/lib/progress/atl-progress.css +10 -0
  60. package/src/lib/radio/atl-radio.css +11 -1
  61. package/src/lib/radio/atl-radio.d.ts.map +1 -1
  62. package/src/lib/radio/atl-radio.js +5 -3
  63. package/src/lib/radio/atl-radio.js.map +1 -1
  64. package/src/lib/radio-group/atl-radio-group.css +10 -0
  65. package/src/lib/select/atl-select.css +21 -3
  66. package/src/lib/select/atl-select.d.ts +1 -5
  67. package/src/lib/select/atl-select.d.ts.map +1 -1
  68. package/src/lib/select/atl-select.js +1 -3
  69. package/src/lib/select/atl-select.js.map +1 -1
  70. package/src/lib/skeleton/atl-skeleton.css +10 -0
  71. package/src/lib/spec.d.ts +20 -6
  72. package/src/lib/spec.d.ts.map +1 -1
  73. package/src/lib/spec.js +1 -1
  74. package/src/lib/spec.js.map +1 -1
  75. package/src/lib/stepper/atl-stepper.css +11 -1
  76. package/src/lib/stepper/atl-stepper.d.ts.map +1 -1
  77. package/src/lib/stepper/atl-stepper.js +2 -1
  78. package/src/lib/stepper/atl-stepper.js.map +1 -1
  79. package/src/lib/table/atl-table.css +42 -3
  80. package/src/lib/table/atl-table.d.ts.map +1 -1
  81. package/src/lib/table/atl-table.js +2 -1
  82. package/src/lib/table/atl-table.js.map +1 -1
  83. package/src/lib/tabs/atl-tabs.css +27 -5
  84. package/src/lib/textarea/atl-textarea.css +22 -7
  85. package/src/lib/textarea/atl-textarea.d.ts.map +1 -1
  86. package/src/lib/textarea/atl-textarea.js +2 -1
  87. package/src/lib/textarea/atl-textarea.js.map +1 -1
  88. package/src/lib/toast/atl-toast.css +16 -0
  89. package/src/lib/toast/atl-toast.d.ts.map +1 -1
  90. package/src/lib/toast/atl-toast.js +2 -1
  91. package/src/lib/toast/atl-toast.js.map +1 -1
  92. package/src/lib/toggle/atl-toggle.css +11 -1
  93. package/src/lib/toggle/atl-toggle.d.ts +1 -5
  94. package/src/lib/toggle/atl-toggle.d.ts.map +1 -1
  95. package/src/lib/toggle/atl-toggle.js +2 -3
  96. package/src/lib/toggle/atl-toggle.js.map +1 -1
  97. package/src/lib/tooltip/atl-tooltip.css +16 -0
  98. package/styles/tokens.css +12 -0
@@ -1,3 +1,29 @@
1
+ /* Geometry contract: every size this component states is a border-box size.
2
+ * Declared with the component rather than as a global reset, so it ships in the
3
+ * same file as the sizes it governs and no consuming app has to supply one.
4
+ * Gated by check:box-sizing; the resulting boxes are measured by check:geometry.
5
+ * See ADR-0043. */
6
+ :is(
7
+ .atl-chat,
8
+ .atl-chat-header,
9
+ .atl-chat-input,
10
+ .atl-chat-message,
11
+ .atl-chat-messages,
12
+ .atl-chat-suggestion,
13
+ .atl-chat-typing
14
+ ),
15
+ :is(
16
+ .atl-chat,
17
+ .atl-chat-header,
18
+ .atl-chat-input,
19
+ .atl-chat-message,
20
+ .atl-chat-messages,
21
+ .atl-chat-suggestion,
22
+ .atl-chat-typing
23
+ ) * {
24
+ box-sizing: border-box;
25
+ }
26
+
1
27
  /* ── Host wrapper ──────────────────────────────────────────────────────────── */
2
28
  .atl-chat {
3
29
  display: contents;
@@ -70,7 +96,7 @@
70
96
  height: 35rem;
71
97
  border-radius: var(--ui-radius-xl);
72
98
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.18);
73
- z-index: 100;
99
+ z-index: var(--ui-z-dropdown);
74
100
  }
75
101
 
76
102
  .atl-chat.variant-popup .fab-bubble {
@@ -111,7 +137,7 @@
111
137
  width: 100%;
112
138
  height: 100%;
113
139
  min-height: 24rem;
114
- border: 1px solid var(--ui-color-border);
140
+ border: var(--ui-border-width) solid var(--ui-color-border);
115
141
  border-radius: var(--ui-radius-xl);
116
142
  }
117
143
 
@@ -128,7 +154,7 @@
128
154
  justify-content: space-between;
129
155
  gap: var(--ui-spacing-3);
130
156
  padding: var(--ui-spacing-3) var(--ui-spacing-4);
131
- border-bottom: 1px solid var(--ui-color-border);
157
+ border-bottom: var(--ui-border-width) solid var(--ui-color-border);
132
158
  flex-shrink: 0;
133
159
  }
134
160
 
@@ -149,11 +175,11 @@
149
175
  align-items: center;
150
176
  justify-content: center;
151
177
  flex-shrink: 0;
152
- width: 2rem;
153
- height: 2rem;
178
+ width: var(--ui-control-height-sm);
179
+ height: var(--ui-control-height-sm);
154
180
  padding: 0;
155
181
  background: transparent;
156
- border: 1px solid var(--ui-color-border);
182
+ border: var(--ui-border-width) solid var(--ui-color-border);
157
183
  border-radius: var(--ui-radius-sm);
158
184
  cursor: pointer;
159
185
  color: var(--ui-color-text-muted);
@@ -220,7 +246,7 @@
220
246
 
221
247
  .atl-chat-message.is-failed {
222
248
  background: var(--ui-color-surface-sunken);
223
- border: 1px dashed var(--ui-color-danger);
249
+ border: var(--ui-border-width) dashed var(--ui-color-danger);
224
250
  color: var(--ui-color-text);
225
251
  }
226
252
 
@@ -310,7 +336,7 @@
310
336
  padding: var(--ui-spacing-3) var(--ui-spacing-4);
311
337
  background: var(--ui-color-surface);
312
338
  color: var(--ui-color-text);
313
- border: 1px solid var(--ui-color-border);
339
+ border: var(--ui-border-width) solid var(--ui-color-border);
314
340
  border-radius: var(--ui-radius-lg);
315
341
  font-family: var(--ui-font-family);
316
342
  text-align: left;
@@ -349,7 +375,7 @@
349
375
  align-items: flex-end;
350
376
  gap: var(--ui-spacing-2);
351
377
  padding: var(--ui-spacing-3) var(--ui-spacing-4);
352
- border-top: 1px solid var(--ui-color-border);
378
+ border-top: var(--ui-border-width) solid var(--ui-color-border);
353
379
  background: var(--ui-color-surface);
354
380
  flex-shrink: 0;
355
381
  }
@@ -358,7 +384,7 @@
358
384
  flex: 1;
359
385
  min-width: 0;
360
386
  padding: var(--ui-spacing-2) var(--ui-spacing-3);
361
- border: 1px solid var(--ui-color-input-border, var(--ui-color-border));
387
+ border: var(--ui-border-width) solid var(--ui-color-input-border, var(--ui-color-border));
362
388
  border-radius: var(--ui-radius-md);
363
389
  background: var(--ui-color-surface-sunken);
364
390
  color: var(--ui-color-text);
@@ -394,7 +420,7 @@
394
420
  justify-content: center;
395
421
  flex-shrink: 0;
396
422
  padding: var(--ui-spacing-2) var(--ui-spacing-4);
397
- border: 1px solid transparent;
423
+ border: var(--ui-border-width) solid transparent;
398
424
  border-radius: var(--ui-radius-md);
399
425
  font-family: var(--ui-font-family);
400
426
  font-size: var(--ui-font-size-sm);
@@ -1 +1 @@
1
- {"version":3,"file":"atl-chat.d.ts","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/chat/atl-chat.tsx"],"names":[],"mappings":"AAAA,OAAO,EAEL,cAAc,EAGd,SAAS,EACT,sBAAsB,EAOvB,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EACV,kBAAkB,EAClB,aAAa,EACb,cAAc,EACf,MAAM,SAAS,CAAC;AACjB,OAAO,gBAAgB,CAAC;AAgBxB;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,sBAAsB;IACtB,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,oCAAoC;IACpC,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,0DAA0D;IAC1D,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,8CAA8C;IAC9C,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,EACtB,OAAkB,EAClB,MAAe,EACf,IAAY,EACZ,YAAY,EACZ,QAAQ,GACT,EAAE,YAAY,+BAuHd;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EACR,EAAE,cAAc,CAAC,cAAc,CAAC,+BAiChC;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EACR,EAAE,cAAc,CAAC,cAAc,CAAC,+BAoBhC;AAED;;GAEG;AACH,MAAM,WAAW,mBAAoB,SAAQ,cAAc,CAAC,cAAc,CAAC;IACzE,6BAA6B;IAC7B,IAAI,CAAC,EAAE,kBAAkB,CAAC;IAC1B,uDAAuD;IACvD,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,cAAc,CAAC,EAC7B,IAAkB,EAClB,MAAc,EACd,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EACR,EAAE,mBAAmB,+BAcrB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,kBAAmB,SAAQ,cAAc,CAAC,cAAc,CAAC;IACxE,oEAAoE;IACpE,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,aAAa,CAAC,EAC5B,MAAc,EACd,SAAS,EACT,GAAG,IAAI,EACR,EAAE,kBAAkB,+BAcpB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,oCAAoC;IACpC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6CAA6C;IAC7C,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,iBAAiB,CAAC,EAChC,KAAK,EACL,IAAI,EACJ,UAAU,EACV,SAAS,GACV,EAAE,sBAAsB,+BAexB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,iBACf,SAAQ,IAAI,CAAC,sBAAsB,CAAC,mBAAmB,CAAC,EAAE,UAAU,CAAC;IACrE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,aAAa,EACb,MAAM,EACN,MAAM,EACN,WAAW,EACX,SAAuC,EACvC,GAAG,IAAI,EACR,EAAE,iBAAiB,+BAuEnB"}
1
+ {"version":3,"file":"atl-chat.d.ts","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/chat/atl-chat.tsx"],"names":[],"mappings":"AAAA,OAAO,EAEL,cAAc,EAGd,SAAS,EACT,sBAAsB,EAOvB,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EACV,kBAAkB,EAClB,aAAa,EACb,cAAc,EACf,MAAM,SAAS,CAAC;AACjB,OAAO,gBAAgB,CAAC;AAiBxB;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,sBAAsB;IACtB,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,oCAAoC;IACpC,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,0DAA0D;IAC1D,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,8CAA8C;IAC9C,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,EACtB,OAAkB,EAClB,MAAe,EACf,IAAY,EACZ,YAAY,EACZ,QAAQ,GACT,EAAE,YAAY,+BAuHd;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EACR,EAAE,cAAc,CAAC,cAAc,CAAC,+BAmBhC;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EACR,EAAE,cAAc,CAAC,cAAc,CAAC,+BAoBhC;AAED;;GAEG;AACH,MAAM,WAAW,mBAAoB,SAAQ,cAAc,CAAC,cAAc,CAAC;IACzE,6BAA6B;IAC7B,IAAI,CAAC,EAAE,kBAAkB,CAAC;IAC1B,uDAAuD;IACvD,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,cAAc,CAAC,EAC7B,IAAkB,EAClB,MAAc,EACd,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EACR,EAAE,mBAAmB,+BAcrB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,kBAAmB,SAAQ,cAAc,CAAC,cAAc,CAAC;IACxE,oEAAoE;IACpE,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,aAAa,CAAC,EAC5B,MAAc,EACd,SAAS,EACT,GAAG,IAAI,EACR,EAAE,kBAAkB,+BAcpB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,oCAAoC;IACpC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6CAA6C;IAC7C,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,iBAAiB,CAAC,EAChC,KAAK,EACL,IAAI,EACJ,UAAU,EACV,SAAS,GACV,EAAE,sBAAsB,+BAexB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,iBACf,SAAQ,IAAI,CAAC,sBAAsB,CAAC,mBAAmB,CAAC,EAAE,UAAU,CAAC;IACrE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,aAAa,EACb,MAAM,EACN,MAAM,EACN,WAAW,EACX,SAAuC,EACvC,GAAG,IAAI,EACR,EAAE,iBAAiB,+BAuEnB"}
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { createContext, useContext, useEffect, useId, useRef, useState, } from 'react';
3
3
  import './atl-chat.css';
4
+ import { AtlIcon } from '../icon/atl-icon';
4
5
  const ChatContext = createContext({
5
6
  headerId: '',
6
7
  status: 'idle',
@@ -93,7 +94,7 @@ export function AtlChat({ variant = 'drawer', status = 'idle', open = false, onO
93
94
  */
94
95
  export function AtlChatHeader({ children, className, ...rest }) {
95
96
  const ctx = useContext(ChatContext);
96
- return (_jsxs("div", { id: ctx.headerId, className: ['atl-chat-header', className].filter(Boolean).join(' '), ...rest, children: [_jsx("div", { className: "title-block", children: children }), _jsx("button", { type: "button", className: "close-btn", "aria-label": "Close chat", onClick: ctx.close, children: _jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), _jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }) })] }));
97
+ return (_jsxs("div", { id: ctx.headerId, className: ['atl-chat-header', className].filter(Boolean).join(' '), ...rest, children: [_jsx("div", { className: "title-block", children: children }), _jsx("button", { type: "button", className: "close-btn", "aria-label": "Close chat", onClick: ctx.close, children: _jsx(AtlIcon, { name: "close", size: "sm" }) })] }));
97
98
  }
98
99
  /**
99
100
  * Scrollable message list. Project `AtlChatMessage`, `AtlChatTyping`, or
@@ -1 +1 @@
1
- {"version":3,"file":"atl-chat.js","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/chat/atl-chat.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n ChangeEvent,\n HTMLAttributes,\n KeyboardEvent,\n MouseEvent,\n ReactNode,\n TextareaHTMLAttributes,\n createContext,\n useContext,\n useEffect,\n useId,\n useRef,\n useState,\n} from 'react';\nimport type {\n AtlChatMessageRole,\n AtlChatStatus,\n AtlChatVariant,\n} from '../spec';\nimport './atl-chat.css';\n\ninterface ChatContextValue {\n headerId: string;\n status: AtlChatStatus;\n close: () => void;\n toggle: () => void;\n}\n\nconst ChatContext = createContext<ChatContextValue>({\n headerId: '',\n status: 'idle',\n close: () => undefined,\n toggle: () => undefined,\n});\n\n/**\n * Properties for the AtlChat component.\n */\nexport interface AtlChatProps {\n /** Layout variant. */\n variant?: AtlChatVariant;\n /** Connection / response status. */\n status?: AtlChatStatus;\n /** Whether the chat is open (drawer / popup variants). */\n open?: boolean;\n /** Callback when open state should change. */\n onOpenChange?: (open: boolean) => void;\n children?: ReactNode;\n}\n\n/**\n * AI assistant surface. Three layout variants share the same content slots:\n * `drawer` (slide-in panel), `popup` (floating bubble + window), `inline`\n * (embedded card). Compose with `AtlChatHeader`, `AtlChatMessages`,\n * `AtlChatMessage`, `AtlChatTyping`, `AtlChatSuggestion`, `AtlChatInput`.\n */\nexport function AtlChat({\n variant = 'drawer',\n status = 'idle',\n open = false,\n onOpenChange,\n children,\n}: AtlChatProps) {\n const dialogRef = useRef<HTMLDialogElement>(null);\n const headerId = useId();\n const triggerElRef = useRef<Element | null>(null);\n\n useEffect(() => {\n if (variant !== 'drawer') return;\n const dialog = dialogRef.current;\n if (!dialog) return;\n if (open) {\n triggerElRef.current = document.activeElement;\n if (!dialog.open) dialog.showModal();\n } else {\n if (dialog.open) dialog.close();\n (triggerElRef.current as HTMLElement | null)?.focus();\n triggerElRef.current = null;\n }\n }, [open, variant]);\n\n // Auto-focus the input on open for drawer / popup. Inline keeps user focus.\n const hostRef = useRef<HTMLDivElement>(null);\n useEffect(() => {\n if (!open) return;\n if (variant === 'inline') return;\n const host = hostRef.current;\n if (!host) return;\n requestAnimationFrame(() => {\n host.querySelector<HTMLTextAreaElement>('textarea')?.focus();\n });\n }, [open, variant]);\n\n useEffect(() => {\n if (variant !== 'drawer') return;\n const dialog = dialogRef.current;\n if (!dialog) return;\n const onClose = () => onOpenChange?.(false);\n const onCancel = (e: Event) => {\n e.preventDefault();\n onOpenChange?.(false);\n };\n dialog.addEventListener('close', onClose);\n dialog.addEventListener('cancel', onCancel);\n return () => {\n dialog.removeEventListener('close', onClose);\n dialog.removeEventListener('cancel', onCancel);\n };\n }, [onOpenChange, variant]);\n\n const handleBackdropClick = (e: MouseEvent<HTMLDialogElement>) => {\n if (e.target === dialogRef.current) onOpenChange?.(false);\n };\n\n const hostClass = [\n 'atl-chat',\n `variant-${variant}`,\n `status-${status}`,\n open && 'is-open',\n ]\n .filter(Boolean)\n .join(' ');\n\n const ctx: ChatContextValue = {\n headerId,\n status,\n close: () => onOpenChange?.(false),\n toggle: () => onOpenChange?.(!open),\n };\n\n return (\n <ChatContext.Provider value={ctx}>\n <div ref={hostRef} className={hostClass}>\n {variant === 'drawer' && (\n <dialog\n ref={dialogRef}\n aria-labelledby={headerId}\n aria-modal=\"true\"\n onClick={handleBackdropClick}\n >\n <div\n className=\"surface drawer-surface\"\n onClick={(e) => e.stopPropagation()}\n >\n {children}\n </div>\n </dialog>\n )}\n {variant === 'popup' && (\n <>\n {open && (\n <div\n className=\"surface popup-surface\"\n role=\"dialog\"\n aria-labelledby={headerId}\n >\n {children}\n </div>\n )}\n <button\n type=\"button\"\n className=\"fab-bubble\"\n aria-label={open ? 'Close AI assistant' : 'Open AI assistant'}\n aria-expanded={open}\n onClick={() => onOpenChange?.(!open)}\n >\n <span aria-hidden=\"true\">AI</span>\n </button>\n </>\n )}\n {variant === 'inline' && (\n <section\n className=\"surface inline-surface\"\n aria-labelledby={headerId}\n >\n {children}\n </section>\n )}\n </div>\n </ChatContext.Provider>\n );\n}\n\n/**\n * Header slot for `AtlChat`. Holds the title block; the close button\n * is rendered automatically (hidden on the inline variant via CSS).\n */\nexport function AtlChatHeader({\n children,\n className,\n ...rest\n}: HTMLAttributes<HTMLDivElement>) {\n const ctx = useContext(ChatContext);\n return (\n <div\n id={ctx.headerId}\n className={['atl-chat-header', className].filter(Boolean).join(' ')}\n {...rest}\n >\n <div className=\"title-block\">{children}</div>\n <button\n type=\"button\"\n className=\"close-btn\"\n aria-label=\"Close chat\"\n onClick={ctx.close}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" />\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n </button>\n </div>\n );\n}\n\n/**\n * Scrollable message list. Project `AtlChatMessage`, `AtlChatTyping`, or\n * `AtlChatSuggestion` children inside. Auto-scrolls to the bottom whenever\n * children are added or content changes — important for streaming responses\n * where new tokens are appended live.\n */\nexport function AtlChatMessages({\n children,\n className,\n ...rest\n}: HTMLAttributes<HTMLDivElement>) {\n const ref = useRef<HTMLDivElement>(null);\n useEffect(() => {\n const el = ref.current;\n if (!el) return;\n const stickToBottom = () => { el.scrollTop = el.scrollHeight; };\n stickToBottom();\n const observer = new MutationObserver(stickToBottom);\n observer.observe(el, { childList: true, subtree: true, characterData: true });\n return () => observer.disconnect();\n }, []);\n return (\n <div\n ref={ref}\n className={['atl-chat-messages', className].filter(Boolean).join(' ')}\n {...rest}\n >\n {children}\n </div>\n );\n}\n\n/**\n * A single chat message. Role drives bubble alignment and color.\n */\nexport interface AtlChatMessageProps extends HTMLAttributes<HTMLDivElement> {\n /** Sender of the message. */\n role?: AtlChatMessageRole;\n /** Marks the message as failed (red dashed border). */\n failed?: boolean;\n}\n\nexport function AtlChatMessage({\n role = 'assistant',\n failed = false,\n children,\n className,\n ...rest\n}: AtlChatMessageProps) {\n const classes = [\n 'atl-chat-message',\n `role-${role}`,\n failed && 'is-failed',\n className,\n ]\n .filter(Boolean)\n .join(' ');\n return (\n <div role=\"listitem\" className={classes} {...rest}>\n {children}\n </div>\n );\n}\n\n/**\n * Typing indicator (three animated dots).\n *\n * Two display modes:\n * - **Standalone bubble** (default) — render at the end of the message\n * list to show \"the assistant is starting to respond\".\n * - **Inline cursor** (`inline`) — render as the LAST child INSIDE the\n * currently-streaming `AtlChatMessage` so the dots read as a typing\n * caret at the end of the partial text.\n */\nexport interface AtlChatTypingProps extends HTMLAttributes<HTMLDivElement> {\n /** When true, renders as an inline cursor without bubble chrome. */\n inline?: boolean;\n}\n\nexport function AtlChatTyping({\n inline = false,\n className,\n ...rest\n}: AtlChatTypingProps) {\n const classes = [\n 'atl-chat-typing',\n inline && 'is-inline',\n className,\n ].filter(Boolean).join(' ');\n return (\n <div role=\"status\" aria-live=\"polite\" className={classes} {...rest}>\n <span className=\"dot\" />\n <span className=\"dot\" />\n <span className=\"dot\" />\n <span className=\"sr-only\">Assistant is typing</span>\n </div>\n );\n}\n\n/**\n * Tappable suggestion chip used in the empty state to seed a conversation.\n */\nexport interface AtlChatSuggestionProps {\n /** Primary label of the suggestion. */\n label: string;\n /** Optional secondary hint text. */\n hint?: string;\n /** Fires the label string when activated. */\n onSelected?: (label: string) => void;\n className?: string;\n}\n\nexport function AtlChatSuggestion({\n label,\n hint,\n onSelected,\n className,\n}: AtlChatSuggestionProps) {\n return (\n <div\n className={['atl-chat-suggestion', className].filter(Boolean).join(' ')}\n >\n <button\n type=\"button\"\n className=\"chip\"\n onClick={() => onSelected?.(label)}\n >\n <span className=\"chip-label\">{label}</span>\n {hint && <span className=\"chip-hint\">{hint}</span>}\n </button>\n </div>\n );\n}\n\n/**\n * Composable input footer for `AtlChat`. Wraps a textarea and emits\n * `onSend` (or `onStop` when the chat status is `'streaming'`).\n *\n * The action button automatically switches between primary \"Send\" and\n * danger \"Stop\" based on the parent chat's status.\n */\nexport interface AtlChatInputProps\n extends Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, 'onChange'> {\n value?: string;\n onValueChange?: (value: string) => void;\n onSend?: (text: string) => void;\n onStop?: () => void;\n /** Accessible label for the input field. */\n ariaLabel?: string;\n}\n\nexport function AtlChatInput({\n value,\n onValueChange,\n onSend,\n onStop,\n placeholder,\n ariaLabel = 'Message your AI assistant',\n ...rest\n}: AtlChatInputProps) {\n const ctx = useContext(ChatContext);\n const isStreaming = ctx.status === 'streaming';\n const [internal, setInternal] = useState('');\n const isControlled = value !== undefined;\n const current = isControlled ? value : internal;\n\n const setCurrent = (next: string) => {\n if (!isControlled) setInternal(next);\n onValueChange?.(next);\n };\n\n const effectivePlaceholder =\n placeholder ??\n (isStreaming\n ? 'Waiting for response…'\n : ctx.status === 'error'\n ? 'Try again…'\n : 'Message your AI assistant…');\n\n const emitSend = () => {\n const text = current.trim();\n if (!text || isStreaming) return;\n onSend?.(text);\n setCurrent('');\n };\n\n const handleChange = (e: ChangeEvent<HTMLTextAreaElement>) => {\n setCurrent(e.target.value);\n };\n\n const handleKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n emitSend();\n }\n };\n\n return (\n <div className=\"atl-chat-input\">\n <textarea\n className=\"field\"\n rows={1}\n value={current}\n placeholder={effectivePlaceholder}\n disabled={isStreaming}\n aria-label={ariaLabel}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n {...rest}\n />\n {isStreaming ? (\n <button\n type=\"button\"\n className=\"action-btn variant-danger size-md\"\n onClick={onStop}\n >\n Stop\n </button>\n ) : (\n <button\n type=\"button\"\n className=\"action-btn variant-primary size-md\"\n disabled={!current.trim()}\n onClick={emitSend}\n >\n Send\n </button>\n )}\n </div>\n );\n}\n"]}
1
+ {"version":3,"file":"atl-chat.js","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/chat/atl-chat.tsx"],"names":[],"mappings":";AAAA,OAAO,EAOL,aAAa,EACb,UAAU,EACV,SAAS,EACT,KAAK,EACL,MAAM,EACN,QAAQ,GACT,MAAM,OAAO,CAAC;AAMf,OAAO,gBAAgB,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAS3C,MAAM,WAAW,GAAG,aAAa,CAAmB;IAClD,QAAQ,EAAE,EAAE;IACZ,MAAM,EAAE,MAAM;IACd,KAAK,EAAE,GAAG,EAAE,CAAC,SAAS;IACtB,MAAM,EAAE,GAAG,EAAE,CAAC,SAAS;CACxB,CAAC,CAAC;AAiBH;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CAAC,EACtB,OAAO,GAAG,QAAQ,EAClB,MAAM,GAAG,MAAM,EACf,IAAI,GAAG,KAAK,EACZ,YAAY,EACZ,QAAQ,GACK;IACb,MAAM,SAAS,GAAG,MAAM,CAAoB,IAAI,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAG,KAAK,EAAE,CAAC;IACzB,MAAM,YAAY,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAElD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,OAAO,KAAK,QAAQ;YAAE,OAAO;QACjC,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC;QACjC,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,IAAI,IAAI,EAAE,CAAC;YACT,YAAY,CAAC,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC;YAC9C,IAAI,CAAC,MAAM,CAAC,IAAI;gBAAE,MAAM,CAAC,SAAS,EAAE,CAAC;QACvC,CAAC;aAAM,CAAC;YACN,IAAI,MAAM,CAAC,IAAI;gBAAE,MAAM,CAAC,KAAK,EAAE,CAAC;YAC/B,YAAY,CAAC,OAA8B,EAAE,KAAK,EAAE,CAAC;YACtD,YAAY,CAAC,OAAO,GAAG,IAAI,CAAC;QAC9B,CAAC;IACH,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IAEpB,4EAA4E;IAC5E,MAAM,OAAO,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAC7C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,IAAI,OAAO,KAAK,QAAQ;YAAE,OAAO;QACjC,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC;QAC7B,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,qBAAqB,CAAC,GAAG,EAAE;YACzB,IAAI,CAAC,aAAa,CAAsB,UAAU,CAAC,EAAE,KAAK,EAAE,CAAC;QAC/D,CAAC,CAAC,CAAC;IACL,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IAEpB,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,OAAO,KAAK,QAAQ;YAAE,OAAO;QACjC,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC;QACjC,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,YAAY,EAAE,CAAC,KAAK,CAAC,CAAC;QAC5C,MAAM,QAAQ,GAAG,CAAC,CAAQ,EAAE,EAAE;YAC5B,CAAC,CAAC,cAAc,EAAE,CAAC;YACnB,YAAY,EAAE,CAAC,KAAK,CAAC,CAAC;QACxB,CAAC,CAAC;QACF,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC1C,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC5C,OAAO,GAAG,EAAE;YACV,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC7C,MAAM,CAAC,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACjD,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC;IAE5B,MAAM,mBAAmB,GAAG,CAAC,CAAgC,EAAE,EAAE;QAC/D,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,OAAO;YAAE,YAAY,EAAE,CAAC,KAAK,CAAC,CAAC;IAC5D,CAAC,CAAC;IAEF,MAAM,SAAS,GAAG;QAChB,UAAU;QACV,WAAW,OAAO,EAAE;QACpB,UAAU,MAAM,EAAE;QAClB,IAAI,IAAI,SAAS;KAClB;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,CAAC;IAEb,MAAM,GAAG,GAAqB;QAC5B,QAAQ;QACR,MAAM;QACN,KAAK,EAAE,GAAG,EAAE,CAAC,YAAY,EAAE,CAAC,KAAK,CAAC;QAClC,MAAM,EAAE,GAAG,EAAE,CAAC,YAAY,EAAE,CAAC,CAAC,IAAI,CAAC;KACpC,CAAC;IAEF,OAAO,CACL,KAAC,WAAW,CAAC,QAAQ,IAAC,KAAK,EAAE,GAAG,YAC9B,eAAK,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,aACpC,OAAO,KAAK,QAAQ,IAAI,CACvB,iBACE,GAAG,EAAE,SAAS,qBACG,QAAQ,gBACd,MAAM,EACjB,OAAO,EAAE,mBAAmB,YAE5B,cACE,SAAS,EAAC,wBAAwB,EAClC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,EAAE,YAElC,QAAQ,GACL,GACC,CACV,EACA,OAAO,KAAK,OAAO,IAAI,CACtB,8BACG,IAAI,IAAI,CACP,cACE,SAAS,EAAC,uBAAuB,EACjC,IAAI,EAAC,QAAQ,qBACI,QAAQ,YAExB,QAAQ,GACL,CACP,EACD,iBACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,YAAY,gBACV,IAAI,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,mBAAmB,mBAC9C,IAAI,EACnB,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,EAAE,CAAC,CAAC,IAAI,CAAC,YAEpC,8BAAkB,MAAM,mBAAU,GAC3B,IACR,CACJ,EACA,OAAO,KAAK,QAAQ,IAAI,CACvB,kBACE,SAAS,EAAC,wBAAwB,qBACjB,QAAQ,YAExB,QAAQ,GACD,CACX,IACG,GACe,CACxB,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,EAC5B,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EACwB;IAC/B,MAAM,GAAG,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;IACpC,OAAO,CACL,eACE,EAAE,EAAE,GAAG,CAAC,QAAQ,EAChB,SAAS,EAAE,CAAC,iBAAiB,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KAC/D,IAAI,aAER,cAAK,SAAS,EAAC,aAAa,YAAE,QAAQ,GAAO,EAC7C,iBACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,WAAW,gBACV,YAAY,EACvB,OAAO,EAAE,GAAG,CAAC,KAAK,YAElB,KAAC,OAAO,IAAC,IAAI,EAAC,OAAO,EAAC,IAAI,EAAC,IAAI,GAAG,GAC3B,IACL,CACP,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,EAC9B,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EACwB;IAC/B,MAAM,GAAG,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IACzC,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC;QACvB,IAAI,CAAC,EAAE;YAAE,OAAO;QAChB,MAAM,aAAa,GAAG,GAAG,EAAE,GAAG,EAAE,CAAC,SAAS,GAAG,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAChE,aAAa,EAAE,CAAC;QAChB,MAAM,QAAQ,GAAG,IAAI,gBAAgB,CAAC,aAAa,CAAC,CAAC;QACrD,QAAQ,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9E,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;IACrC,CAAC,EAAE,EAAE,CAAC,CAAC;IACP,OAAO,CACL,cACE,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,CAAC,mBAAmB,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KACjE,IAAI,YAEP,QAAQ,GACL,CACP,CAAC;AACJ,CAAC;AAYD,MAAM,UAAU,cAAc,CAAC,EAC7B,IAAI,GAAG,WAAW,EAClB,MAAM,GAAG,KAAK,EACd,QAAQ,EACR,SAAS,EACT,GAAG,IAAI,EACa;IACpB,MAAM,OAAO,GAAG;QACd,kBAAkB;QAClB,QAAQ,IAAI,EAAE;QACd,MAAM,IAAI,WAAW;QACrB,SAAS;KACV;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,CAAC;IACb,OAAO,CACL,cAAK,IAAI,EAAC,UAAU,EAAC,SAAS,EAAE,OAAO,KAAM,IAAI,YAC9C,QAAQ,GACL,CACP,CAAC;AACJ,CAAC;AAiBD,MAAM,UAAU,aAAa,CAAC,EAC5B,MAAM,GAAG,KAAK,EACd,SAAS,EACT,GAAG,IAAI,EACY;IACnB,MAAM,OAAO,GAAG;QACd,iBAAiB;QACjB,MAAM,IAAI,WAAW;QACrB,SAAS;KACV,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC5B,OAAO,CACL,eAAK,IAAI,EAAC,QAAQ,eAAW,QAAQ,EAAC,SAAS,EAAE,OAAO,KAAM,IAAI,aAChE,eAAM,SAAS,EAAC,KAAK,GAAG,EACxB,eAAM,SAAS,EAAC,KAAK,GAAG,EACxB,eAAM,SAAS,EAAC,KAAK,GAAG,EACxB,eAAM,SAAS,EAAC,SAAS,oCAA2B,IAChD,CACP,CAAC;AACJ,CAAC;AAeD,MAAM,UAAU,iBAAiB,CAAC,EAChC,KAAK,EACL,IAAI,EACJ,UAAU,EACV,SAAS,GACc;IACvB,OAAO,CACL,cACE,SAAS,EAAE,CAAC,qBAAqB,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,YAEvE,kBACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,MAAM,EAChB,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,aAElC,eAAM,SAAS,EAAC,YAAY,YAAE,KAAK,GAAQ,EAC1C,IAAI,IAAI,eAAM,SAAS,EAAC,WAAW,YAAE,IAAI,GAAQ,IAC3C,GACL,CACP,CAAC;AACJ,CAAC;AAmBD,MAAM,UAAU,YAAY,CAAC,EAC3B,KAAK,EACL,aAAa,EACb,MAAM,EACN,MAAM,EACN,WAAW,EACX,SAAS,GAAG,2BAA2B,EACvC,GAAG,IAAI,EACW;IAClB,MAAM,GAAG,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;IACpC,MAAM,WAAW,GAAG,GAAG,CAAC,MAAM,KAAK,WAAW,CAAC;IAC/C,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC7C,MAAM,YAAY,GAAG,KAAK,KAAK,SAAS,CAAC;IACzC,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC;IAEhD,MAAM,UAAU,GAAG,CAAC,IAAY,EAAE,EAAE;QAClC,IAAI,CAAC,YAAY;YAAE,WAAW,CAAC,IAAI,CAAC,CAAC;QACrC,aAAa,EAAE,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC,CAAC;IAEF,MAAM,oBAAoB,GACxB,WAAW;QACX,CAAC,WAAW;YACV,CAAC,CAAC,uBAAuB;YACzB,CAAC,CAAC,GAAG,CAAC,MAAM,KAAK,OAAO;gBACtB,CAAC,CAAC,YAAY;gBACd,CAAC,CAAC,4BAA4B,CAAC,CAAC;IAEtC,MAAM,QAAQ,GAAG,GAAG,EAAE;QACpB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,IAAI,IAAI,WAAW;YAAE,OAAO;QACjC,MAAM,EAAE,CAAC,IAAI,CAAC,CAAC;QACf,UAAU,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC,CAAC;IAEF,MAAM,YAAY,GAAG,CAAC,CAAmC,EAAE,EAAE;QAC3D,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC,CAAC;IAEF,MAAM,aAAa,GAAG,CAAC,CAAqC,EAAE,EAAE;QAC9D,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;YACrC,CAAC,CAAC,cAAc,EAAE,CAAC;YACnB,QAAQ,EAAE,CAAC;QACb,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,CACL,eAAK,SAAS,EAAC,gBAAgB,aAC7B,mBACE,SAAS,EAAC,OAAO,EACjB,IAAI,EAAE,CAAC,EACP,KAAK,EAAE,OAAO,EACd,WAAW,EAAE,oBAAoB,EACjC,QAAQ,EAAE,WAAW,gBACT,SAAS,EACrB,QAAQ,EAAE,YAAY,EACtB,SAAS,EAAE,aAAa,KACpB,IAAI,GACR,EACD,WAAW,CAAC,CAAC,CAAC,CACb,iBACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,mCAAmC,EAC7C,OAAO,EAAE,MAAM,qBAGR,CACV,CAAC,CAAC,CAAC,CACF,iBACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,oCAAoC,EAC9C,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EACzB,OAAO,EAAE,QAAQ,qBAGV,CACV,IACG,CACP,CAAC;AACJ,CAAC","sourcesContent":["import {\n ChangeEvent,\n HTMLAttributes,\n KeyboardEvent,\n MouseEvent,\n ReactNode,\n TextareaHTMLAttributes,\n createContext,\n useContext,\n useEffect,\n useId,\n useRef,\n useState,\n} from 'react';\nimport type {\n AtlChatMessageRole,\n AtlChatStatus,\n AtlChatVariant,\n} from '../spec';\nimport './atl-chat.css';\nimport { AtlIcon } from '../icon/atl-icon';\n\ninterface ChatContextValue {\n headerId: string;\n status: AtlChatStatus;\n close: () => void;\n toggle: () => void;\n}\n\nconst ChatContext = createContext<ChatContextValue>({\n headerId: '',\n status: 'idle',\n close: () => undefined,\n toggle: () => undefined,\n});\n\n/**\n * Properties for the AtlChat component.\n */\nexport interface AtlChatProps {\n /** Layout variant. */\n variant?: AtlChatVariant;\n /** Connection / response status. */\n status?: AtlChatStatus;\n /** Whether the chat is open (drawer / popup variants). */\n open?: boolean;\n /** Callback when open state should change. */\n onOpenChange?: (open: boolean) => void;\n children?: ReactNode;\n}\n\n/**\n * AI assistant surface. Three layout variants share the same content slots:\n * `drawer` (slide-in panel), `popup` (floating bubble + window), `inline`\n * (embedded card). Compose with `AtlChatHeader`, `AtlChatMessages`,\n * `AtlChatMessage`, `AtlChatTyping`, `AtlChatSuggestion`, `AtlChatInput`.\n */\nexport function AtlChat({\n variant = 'drawer',\n status = 'idle',\n open = false,\n onOpenChange,\n children,\n}: AtlChatProps) {\n const dialogRef = useRef<HTMLDialogElement>(null);\n const headerId = useId();\n const triggerElRef = useRef<Element | null>(null);\n\n useEffect(() => {\n if (variant !== 'drawer') return;\n const dialog = dialogRef.current;\n if (!dialog) return;\n if (open) {\n triggerElRef.current = document.activeElement;\n if (!dialog.open) dialog.showModal();\n } else {\n if (dialog.open) dialog.close();\n (triggerElRef.current as HTMLElement | null)?.focus();\n triggerElRef.current = null;\n }\n }, [open, variant]);\n\n // Auto-focus the input on open for drawer / popup. Inline keeps user focus.\n const hostRef = useRef<HTMLDivElement>(null);\n useEffect(() => {\n if (!open) return;\n if (variant === 'inline') return;\n const host = hostRef.current;\n if (!host) return;\n requestAnimationFrame(() => {\n host.querySelector<HTMLTextAreaElement>('textarea')?.focus();\n });\n }, [open, variant]);\n\n useEffect(() => {\n if (variant !== 'drawer') return;\n const dialog = dialogRef.current;\n if (!dialog) return;\n const onClose = () => onOpenChange?.(false);\n const onCancel = (e: Event) => {\n e.preventDefault();\n onOpenChange?.(false);\n };\n dialog.addEventListener('close', onClose);\n dialog.addEventListener('cancel', onCancel);\n return () => {\n dialog.removeEventListener('close', onClose);\n dialog.removeEventListener('cancel', onCancel);\n };\n }, [onOpenChange, variant]);\n\n const handleBackdropClick = (e: MouseEvent<HTMLDialogElement>) => {\n if (e.target === dialogRef.current) onOpenChange?.(false);\n };\n\n const hostClass = [\n 'atl-chat',\n `variant-${variant}`,\n `status-${status}`,\n open && 'is-open',\n ]\n .filter(Boolean)\n .join(' ');\n\n const ctx: ChatContextValue = {\n headerId,\n status,\n close: () => onOpenChange?.(false),\n toggle: () => onOpenChange?.(!open),\n };\n\n return (\n <ChatContext.Provider value={ctx}>\n <div ref={hostRef} className={hostClass}>\n {variant === 'drawer' && (\n <dialog\n ref={dialogRef}\n aria-labelledby={headerId}\n aria-modal=\"true\"\n onClick={handleBackdropClick}\n >\n <div\n className=\"surface drawer-surface\"\n onClick={(e) => e.stopPropagation()}\n >\n {children}\n </div>\n </dialog>\n )}\n {variant === 'popup' && (\n <>\n {open && (\n <div\n className=\"surface popup-surface\"\n role=\"dialog\"\n aria-labelledby={headerId}\n >\n {children}\n </div>\n )}\n <button\n type=\"button\"\n className=\"fab-bubble\"\n aria-label={open ? 'Close AI assistant' : 'Open AI assistant'}\n aria-expanded={open}\n onClick={() => onOpenChange?.(!open)}\n >\n <span aria-hidden=\"true\">AI</span>\n </button>\n </>\n )}\n {variant === 'inline' && (\n <section\n className=\"surface inline-surface\"\n aria-labelledby={headerId}\n >\n {children}\n </section>\n )}\n </div>\n </ChatContext.Provider>\n );\n}\n\n/**\n * Header slot for `AtlChat`. Holds the title block; the close button\n * is rendered automatically (hidden on the inline variant via CSS).\n */\nexport function AtlChatHeader({\n children,\n className,\n ...rest\n}: HTMLAttributes<HTMLDivElement>) {\n const ctx = useContext(ChatContext);\n return (\n <div\n id={ctx.headerId}\n className={['atl-chat-header', className].filter(Boolean).join(' ')}\n {...rest}\n >\n <div className=\"title-block\">{children}</div>\n <button\n type=\"button\"\n className=\"close-btn\"\n aria-label=\"Close chat\"\n onClick={ctx.close}\n >\n <AtlIcon name=\"close\" size=\"sm\" />\n </button>\n </div>\n );\n}\n\n/**\n * Scrollable message list. Project `AtlChatMessage`, `AtlChatTyping`, or\n * `AtlChatSuggestion` children inside. Auto-scrolls to the bottom whenever\n * children are added or content changes — important for streaming responses\n * where new tokens are appended live.\n */\nexport function AtlChatMessages({\n children,\n className,\n ...rest\n}: HTMLAttributes<HTMLDivElement>) {\n const ref = useRef<HTMLDivElement>(null);\n useEffect(() => {\n const el = ref.current;\n if (!el) return;\n const stickToBottom = () => { el.scrollTop = el.scrollHeight; };\n stickToBottom();\n const observer = new MutationObserver(stickToBottom);\n observer.observe(el, { childList: true, subtree: true, characterData: true });\n return () => observer.disconnect();\n }, []);\n return (\n <div\n ref={ref}\n className={['atl-chat-messages', className].filter(Boolean).join(' ')}\n {...rest}\n >\n {children}\n </div>\n );\n}\n\n/**\n * A single chat message. Role drives bubble alignment and color.\n */\nexport interface AtlChatMessageProps extends HTMLAttributes<HTMLDivElement> {\n /** Sender of the message. */\n role?: AtlChatMessageRole;\n /** Marks the message as failed (red dashed border). */\n failed?: boolean;\n}\n\nexport function AtlChatMessage({\n role = 'assistant',\n failed = false,\n children,\n className,\n ...rest\n}: AtlChatMessageProps) {\n const classes = [\n 'atl-chat-message',\n `role-${role}`,\n failed && 'is-failed',\n className,\n ]\n .filter(Boolean)\n .join(' ');\n return (\n <div role=\"listitem\" className={classes} {...rest}>\n {children}\n </div>\n );\n}\n\n/**\n * Typing indicator (three animated dots).\n *\n * Two display modes:\n * - **Standalone bubble** (default) — render at the end of the message\n * list to show \"the assistant is starting to respond\".\n * - **Inline cursor** (`inline`) — render as the LAST child INSIDE the\n * currently-streaming `AtlChatMessage` so the dots read as a typing\n * caret at the end of the partial text.\n */\nexport interface AtlChatTypingProps extends HTMLAttributes<HTMLDivElement> {\n /** When true, renders as an inline cursor without bubble chrome. */\n inline?: boolean;\n}\n\nexport function AtlChatTyping({\n inline = false,\n className,\n ...rest\n}: AtlChatTypingProps) {\n const classes = [\n 'atl-chat-typing',\n inline && 'is-inline',\n className,\n ].filter(Boolean).join(' ');\n return (\n <div role=\"status\" aria-live=\"polite\" className={classes} {...rest}>\n <span className=\"dot\" />\n <span className=\"dot\" />\n <span className=\"dot\" />\n <span className=\"sr-only\">Assistant is typing</span>\n </div>\n );\n}\n\n/**\n * Tappable suggestion chip used in the empty state to seed a conversation.\n */\nexport interface AtlChatSuggestionProps {\n /** Primary label of the suggestion. */\n label: string;\n /** Optional secondary hint text. */\n hint?: string;\n /** Fires the label string when activated. */\n onSelected?: (label: string) => void;\n className?: string;\n}\n\nexport function AtlChatSuggestion({\n label,\n hint,\n onSelected,\n className,\n}: AtlChatSuggestionProps) {\n return (\n <div\n className={['atl-chat-suggestion', className].filter(Boolean).join(' ')}\n >\n <button\n type=\"button\"\n className=\"chip\"\n onClick={() => onSelected?.(label)}\n >\n <span className=\"chip-label\">{label}</span>\n {hint && <span className=\"chip-hint\">{hint}</span>}\n </button>\n </div>\n );\n}\n\n/**\n * Composable input footer for `AtlChat`. Wraps a textarea and emits\n * `onSend` (or `onStop` when the chat status is `'streaming'`).\n *\n * The action button automatically switches between primary \"Send\" and\n * danger \"Stop\" based on the parent chat's status.\n */\nexport interface AtlChatInputProps\n extends Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, 'onChange'> {\n value?: string;\n onValueChange?: (value: string) => void;\n onSend?: (text: string) => void;\n onStop?: () => void;\n /** Accessible label for the input field. */\n ariaLabel?: string;\n}\n\nexport function AtlChatInput({\n value,\n onValueChange,\n onSend,\n onStop,\n placeholder,\n ariaLabel = 'Message your AI assistant',\n ...rest\n}: AtlChatInputProps) {\n const ctx = useContext(ChatContext);\n const isStreaming = ctx.status === 'streaming';\n const [internal, setInternal] = useState('');\n const isControlled = value !== undefined;\n const current = isControlled ? value : internal;\n\n const setCurrent = (next: string) => {\n if (!isControlled) setInternal(next);\n onValueChange?.(next);\n };\n\n const effectivePlaceholder =\n placeholder ??\n (isStreaming\n ? 'Waiting for response…'\n : ctx.status === 'error'\n ? 'Try again…'\n : 'Message your AI assistant…');\n\n const emitSend = () => {\n const text = current.trim();\n if (!text || isStreaming) return;\n onSend?.(text);\n setCurrent('');\n };\n\n const handleChange = (e: ChangeEvent<HTMLTextAreaElement>) => {\n setCurrent(e.target.value);\n };\n\n const handleKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n emitSend();\n }\n };\n\n return (\n <div className=\"atl-chat-input\">\n <textarea\n className=\"field\"\n rows={1}\n value={current}\n placeholder={effectivePlaceholder}\n disabled={isStreaming}\n aria-label={ariaLabel}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n {...rest}\n />\n {isStreaming ? (\n <button\n type=\"button\"\n className=\"action-btn variant-danger size-md\"\n onClick={onStop}\n >\n Stop\n </button>\n ) : (\n <button\n type=\"button\"\n className=\"action-btn variant-primary size-md\"\n disabled={!current.trim()}\n onClick={emitSend}\n >\n Send\n </button>\n )}\n </div>\n );\n}\n"]}
@@ -1,3 +1,13 @@
1
+ /* Geometry contract: every size this component states is a border-box size.
2
+ * Declared with the component rather than as a global reset, so it ships in the
3
+ * same file as the sizes it governs and no consuming app has to supply one.
4
+ * Gated by check:box-sizing; the resulting boxes are measured by check:geometry.
5
+ * See ADR-0043. */
6
+ .atl-checkbox,
7
+ .atl-checkbox * {
8
+ box-sizing: border-box;
9
+ }
10
+
1
11
  .atl-checkbox {
2
12
  display: block;
3
13
  font-family: var(--ui-font-family);
@@ -21,7 +31,7 @@
21
31
  flex-shrink: 0;
22
32
  width: 1.25rem;
23
33
  height: 1.25rem;
24
- border: 1.5px solid var(--ui-color-border-strong);
34
+ border: var(--ui-border-width-thick) solid var(--ui-color-border-strong);
25
35
  border-radius: var(--ui-radius-sm);
26
36
  background-color: var(--ui-color-input-bg);
27
37
  cursor: pointer;
@@ -55,7 +65,7 @@
55
65
  margin: auto;
56
66
  width: 0.35rem;
57
67
  height: 0.6rem;
58
- border: 2px solid var(--ui-color-text-on-primary);
68
+ border: var(--ui-border-width-thick) solid var(--ui-color-text-on-primary);
59
69
  border-top: none;
60
70
  border-left: none;
61
71
  transform: rotate(45deg) translate(-1px, -1px);
@@ -25,10 +25,6 @@ export interface AtlCheckboxProps extends Omit<InputHTMLAttributes<HTMLInputElem
25
25
  * Array of error messages to display.
26
26
  */
27
27
  errors?: string[];
28
- /**
29
- * Whether the checkbox is read-only.
30
- */
31
- readOnly?: boolean;
32
28
  /**
33
29
  * The content to be rendered as the label for the checkbox.
34
30
  */
@@ -37,5 +33,5 @@ export interface AtlCheckboxProps extends Omit<InputHTMLAttributes<HTMLInputElem
37
33
  /**
38
34
  * A checkbox component for selecting one or more options.
39
35
  */
40
- export declare function AtlCheckbox({ checked, onCheckedChange, indeterminate, invalid, errors, disabled, readOnly: reactReadOnly, readonly: specReadOnly, required, children, className, id, name, ...rest }: AtlCheckboxProps): import("react").JSX.Element;
36
+ export declare function AtlCheckbox({ checked, onCheckedChange, indeterminate, invalid, errors, disabled, required, children, className, id, name, ...rest }: AtlCheckboxProps): import("react").JSX.Element;
41
37
  //# sourceMappingURL=atl-checkbox.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"atl-checkbox.d.ts","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/checkbox/atl-checkbox.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAA4B,MAAM,OAAO,CAAC;AACjF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,oBAAoB,CAAC;AAE5B;;GAEG;AACH,MAAM,WAAW,gBACf,SAAQ,IAAI,CACR,mBAAmB,CAAC,gBAAgB,CAAC,EACrC,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,OAAO,CACvD,EACD,eAAe;IACjB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;OAEG;IACH,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7C;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,EAC1B,OAAe,EACf,eAAe,EACf,aAAqB,EACrB,OAAe,EACf,MAAW,EACX,QAAgB,EAChB,QAAQ,EAAE,aAAa,EACvB,QAAQ,EAAE,YAAY,EACtB,QAAgB,EAChB,QAAQ,EACR,SAAS,EACT,EAAE,EACF,IAAI,EACJ,GAAG,IAAI,EACR,EAAE,gBAAgB,+BAsDlB"}
1
+ {"version":3,"file":"atl-checkbox.d.ts","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/checkbox/atl-checkbox.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAA4B,MAAM,OAAO,CAAC;AACjF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,oBAAoB,CAAC;AAE5B;;GAEG;AACH,MAAM,WAAW,gBACf,SAAQ,IAAI,CACR,mBAAmB,CAAC,gBAAgB,CAAC,EACrC,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,OAAO,CACvD,EACD,eAAe;IACjB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;OAEG;IACH,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7C;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,EAC1B,OAAe,EACf,eAAe,EACf,aAAqB,EACrB,OAAe,EACf,MAAW,EACX,QAAgB,EAChB,QAAgB,EAChB,QAAQ,EACR,SAAS,EACT,EAAE,EACF,IAAI,EACJ,GAAG,IAAI,EACR,EAAE,gBAAgB,+BAoDlB"}
@@ -4,8 +4,7 @@ import './atl-checkbox.css';
4
4
  /**
5
5
  * A checkbox component for selecting one or more options.
6
6
  */
7
- export function AtlCheckbox({ checked = false, onCheckedChange, indeterminate = false, invalid = false, errors = [], disabled = false, readOnly: reactReadOnly, readonly: specReadOnly, required = false, children, className, id, name, ...rest }) {
8
- const readOnly = reactReadOnly ?? specReadOnly ?? false;
7
+ export function AtlCheckbox({ checked = false, onCheckedChange, indeterminate = false, invalid = false, errors = [], disabled = false, required = false, children, className, id, name, ...rest }) {
9
8
  const inputRef = useRef(null);
10
9
  const generatedId = useId();
11
10
  const inputId = id || `checkbox-${generatedId}`;
@@ -24,6 +23,6 @@ export function AtlCheckbox({ checked = false, onCheckedChange, indeterminate =
24
23
  inputRef.current.indeterminate = indeterminate;
25
24
  }
26
25
  }, [indeterminate]);
27
- return (_jsxs("div", { className: classes, children: [_jsxs("label", { htmlFor: inputId, children: [_jsx("input", { ref: inputRef, type: "checkbox", id: inputId, checked: checked, onChange: (e) => onCheckedChange?.(e.target.checked), disabled: disabled, readOnly: readOnly, required: required, "aria-invalid": invalid || undefined, "aria-required": required || undefined, "aria-describedby": errors.length > 0 ? errorId : undefined, name: name, ...rest }), children] }), errors.length > 0 && (_jsx("div", { className: "errors", id: errorId, "aria-live": "polite", children: errors.map((err, i) => (_jsx("p", { className: "error-message", children: err }, i))) }))] }));
26
+ return (_jsxs("div", { className: classes, children: [_jsxs("label", { htmlFor: inputId, children: [_jsx("input", { ref: inputRef, type: "checkbox", id: inputId, checked: checked, onChange: (e) => onCheckedChange?.(e.target.checked), disabled: disabled, required: required, "aria-invalid": invalid || undefined, "aria-required": required || undefined, "aria-describedby": errors.length > 0 ? errorId : undefined, name: name, ...rest }), children] }), errors.length > 0 && (_jsx("div", { className: "errors", id: errorId, "aria-live": "polite", children: errors.map((err, i) => (_jsx("p", { className: "error-message", children: err }, i))) }))] }));
28
27
  }
29
28
  //# sourceMappingURL=atl-checkbox.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"atl-checkbox.js","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/checkbox/atl-checkbox.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAkC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAEjF,OAAO,oBAAoB,CAAC;AAyC5B;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,EAC1B,OAAO,GAAG,KAAK,EACf,eAAe,EACf,aAAa,GAAG,KAAK,EACrB,OAAO,GAAG,KAAK,EACf,MAAM,GAAG,EAAE,EACX,QAAQ,GAAG,KAAK,EAChB,QAAQ,EAAE,aAAa,EACvB,QAAQ,EAAE,YAAY,EACtB,QAAQ,GAAG,KAAK,EAChB,QAAQ,EACR,SAAS,EACT,EAAE,EACF,IAAI,EACJ,GAAG,IAAI,EACU;IACjB,MAAM,QAAQ,GAAG,aAAa,IAAI,YAAY,IAAI,KAAK,CAAC;IACxD,MAAM,QAAQ,GAAG,MAAM,CAAmB,IAAI,CAAC,CAAC;IAChD,MAAM,WAAW,GAAG,KAAK,EAAE,CAAC;IAC5B,MAAM,OAAO,GAAG,EAAE,IAAI,YAAY,WAAW,EAAE,CAAC;IAChD,MAAM,OAAO,GAAG,GAAG,OAAO,SAAS,CAAC;IAEpC,MAAM,OAAO,GAAG;QACd,cAAc;QACd,OAAO,IAAI,YAAY;QACvB,OAAO,IAAI,YAAY;QACvB,QAAQ,IAAI,aAAa;QACzB,SAAS;KACV;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,CAAC;IAEb,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;YACrB,QAAQ,CAAC,OAAO,CAAC,aAAa,GAAG,aAAa,CAAC;QACjD,CAAC;IACH,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC;IAEpB,OAAO,CACL,eAAK,SAAS,EAAE,OAAO,aACrB,iBAAO,OAAO,EAAE,OAAO,aACrB,gBACE,GAAG,EAAE,QAAQ,EACb,IAAI,EAAC,UAAU,EACf,EAAE,EAAE,OAAO,EACX,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EACpD,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,QAAQ,kBACJ,OAAO,IAAI,SAAS,mBACnB,QAAQ,IAAI,SAAS,sBAClB,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,EACzD,IAAI,EAAE,IAAI,KACN,IAAI,GACR,EACD,QAAQ,IACH,EACP,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,CACpB,cAAK,SAAS,EAAC,QAAQ,EAAC,EAAE,EAAE,OAAO,eAAY,QAAQ,YACpD,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,CACtB,YAAW,SAAS,EAAC,eAAe,YACjC,GAAG,IADE,CAAC,CAEL,CACL,CAAC,GACE,CACP,IACG,CACP,CAAC;AACJ,CAAC","sourcesContent":["import { InputHTMLAttributes, ReactNode, useRef, useEffect, useId } from 'react';\nimport type { AtlCheckboxSpec } from '../spec';\nimport './atl-checkbox.css';\n\n/**\n * Properties for the AtlCheckbox component.\n */\nexport interface AtlCheckboxProps\n extends Omit<\n InputHTMLAttributes<HTMLInputElement>,\n 'type' | 'checked' | 'onChange' | 'readOnly' | 'value'\n >,\n AtlCheckboxSpec {\n /**\n * Whether the checkbox is checked.\n */\n checked?: boolean;\n /**\n * Callback triggered when the checked state changes.\n */\n onCheckedChange?: (checked: boolean) => void;\n /**\n * Whether the checkbox is in an indeterminate state.\n */\n indeterminate?: boolean;\n /**\n * Whether the checkbox is in an invalid state.\n */\n invalid?: boolean;\n /**\n * Array of error messages to display.\n */\n errors?: string[];\n /**\n * Whether the checkbox is read-only.\n */\n readOnly?: boolean;\n /**\n * The content to be rendered as the label for the checkbox.\n */\n children?: ReactNode;\n}\n\n/**\n * A checkbox component for selecting one or more options.\n */\nexport function AtlCheckbox({\n checked = false,\n onCheckedChange,\n indeterminate = false,\n invalid = false,\n errors = [],\n disabled = false,\n readOnly: reactReadOnly,\n readonly: specReadOnly,\n required = false,\n children,\n className,\n id,\n name,\n ...rest\n}: AtlCheckboxProps) {\n const readOnly = reactReadOnly ?? specReadOnly ?? false;\n const inputRef = useRef<HTMLInputElement>(null);\n const generatedId = useId();\n const inputId = id || `checkbox-${generatedId}`;\n const errorId = `${inputId}-errors`;\n\n const classes = [\n 'atl-checkbox',\n checked && 'is-checked',\n invalid && 'is-invalid',\n disabled && 'is-disabled',\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n useEffect(() => {\n if (inputRef.current) {\n inputRef.current.indeterminate = indeterminate;\n }\n }, [indeterminate]);\n\n return (\n <div className={classes}>\n <label htmlFor={inputId}>\n <input\n ref={inputRef}\n type=\"checkbox\"\n id={inputId}\n checked={checked}\n onChange={(e) => onCheckedChange?.(e.target.checked)}\n disabled={disabled}\n readOnly={readOnly}\n required={required}\n aria-invalid={invalid || undefined}\n aria-required={required || undefined}\n aria-describedby={errors.length > 0 ? errorId : undefined}\n name={name}\n {...rest}\n />\n {children}\n </label>\n {errors.length > 0 && (\n <div className=\"errors\" id={errorId} aria-live=\"polite\">\n {errors.map((err, i) => (\n <p key={i} className=\"error-message\">\n {err}\n </p>\n ))}\n </div>\n )}\n </div>\n );\n}\n"]}
1
+ {"version":3,"file":"atl-checkbox.js","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/checkbox/atl-checkbox.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAkC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAEjF,OAAO,oBAAoB,CAAC;AAqC5B;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,EAC1B,OAAO,GAAG,KAAK,EACf,eAAe,EACf,aAAa,GAAG,KAAK,EACrB,OAAO,GAAG,KAAK,EACf,MAAM,GAAG,EAAE,EACX,QAAQ,GAAG,KAAK,EAChB,QAAQ,GAAG,KAAK,EAChB,QAAQ,EACR,SAAS,EACT,EAAE,EACF,IAAI,EACJ,GAAG,IAAI,EACU;IACjB,MAAM,QAAQ,GAAG,MAAM,CAAmB,IAAI,CAAC,CAAC;IAChD,MAAM,WAAW,GAAG,KAAK,EAAE,CAAC;IAC5B,MAAM,OAAO,GAAG,EAAE,IAAI,YAAY,WAAW,EAAE,CAAC;IAChD,MAAM,OAAO,GAAG,GAAG,OAAO,SAAS,CAAC;IAEpC,MAAM,OAAO,GAAG;QACd,cAAc;QACd,OAAO,IAAI,YAAY;QACvB,OAAO,IAAI,YAAY;QACvB,QAAQ,IAAI,aAAa;QACzB,SAAS;KACV;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,CAAC;IAEb,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;YACrB,QAAQ,CAAC,OAAO,CAAC,aAAa,GAAG,aAAa,CAAC;QACjD,CAAC;IACH,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC;IAEpB,OAAO,CACL,eAAK,SAAS,EAAE,OAAO,aACrB,iBAAO,OAAO,EAAE,OAAO,aACrB,gBACE,GAAG,EAAE,QAAQ,EACb,IAAI,EAAC,UAAU,EACf,EAAE,EAAE,OAAO,EACX,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EACpD,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,QAAQ,kBACJ,OAAO,IAAI,SAAS,mBACnB,QAAQ,IAAI,SAAS,sBAClB,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,EACzD,IAAI,EAAE,IAAI,KACN,IAAI,GACR,EACD,QAAQ,IACH,EACP,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,CACpB,cAAK,SAAS,EAAC,QAAQ,EAAC,EAAE,EAAE,OAAO,eAAY,QAAQ,YACpD,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,CACtB,YAAW,SAAS,EAAC,eAAe,YACjC,GAAG,IADE,CAAC,CAEL,CACL,CAAC,GACE,CACP,IACG,CACP,CAAC;AACJ,CAAC","sourcesContent":["import { InputHTMLAttributes, ReactNode, useRef, useEffect, useId } from 'react';\nimport type { AtlCheckboxSpec } from '../spec';\nimport './atl-checkbox.css';\n\n/**\n * Properties for the AtlCheckbox component.\n */\nexport interface AtlCheckboxProps\n extends Omit<\n InputHTMLAttributes<HTMLInputElement>,\n 'type' | 'checked' | 'onChange' | 'readOnly' | 'value'\n >,\n AtlCheckboxSpec {\n /**\n * Whether the checkbox is checked.\n */\n checked?: boolean;\n /**\n * Callback triggered when the checked state changes.\n */\n onCheckedChange?: (checked: boolean) => void;\n /**\n * Whether the checkbox is in an indeterminate state.\n */\n indeterminate?: boolean;\n /**\n * Whether the checkbox is in an invalid state.\n */\n invalid?: boolean;\n /**\n * Array of error messages to display.\n */\n errors?: string[];\n /**\n * The content to be rendered as the label for the checkbox.\n */\n children?: ReactNode;\n}\n\n/**\n * A checkbox component for selecting one or more options.\n */\nexport function AtlCheckbox({\n checked = false,\n onCheckedChange,\n indeterminate = false,\n invalid = false,\n errors = [],\n disabled = false,\n required = false,\n children,\n className,\n id,\n name,\n ...rest\n}: AtlCheckboxProps) {\n const inputRef = useRef<HTMLInputElement>(null);\n const generatedId = useId();\n const inputId = id || `checkbox-${generatedId}`;\n const errorId = `${inputId}-errors`;\n\n const classes = [\n 'atl-checkbox',\n checked && 'is-checked',\n invalid && 'is-invalid',\n disabled && 'is-disabled',\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n useEffect(() => {\n if (inputRef.current) {\n inputRef.current.indeterminate = indeterminate;\n }\n }, [indeterminate]);\n\n return (\n <div className={classes}>\n <label htmlFor={inputId}>\n <input\n ref={inputRef}\n type=\"checkbox\"\n id={inputId}\n checked={checked}\n onChange={(e) => onCheckedChange?.(e.target.checked)}\n disabled={disabled}\n required={required}\n aria-invalid={invalid || undefined}\n aria-required={required || undefined}\n aria-describedby={errors.length > 0 ? errorId : undefined}\n name={name}\n {...rest}\n />\n {children}\n </label>\n {errors.length > 0 && (\n <div className=\"errors\" id={errorId} aria-live=\"polite\">\n {errors.map((err, i) => (\n <p key={i} className=\"error-message\">\n {err}\n </p>\n ))}\n </div>\n )}\n </div>\n );\n}\n"]}
@@ -1,10 +1,20 @@
1
+ /* Geometry contract: every size this component states is a border-box size.
2
+ * Declared with the component rather than as a global reset, so it ships in the
3
+ * same file as the sizes it governs and no consuming app has to supply one.
4
+ * Gated by check:box-sizing; the resulting boxes are measured by check:geometry.
5
+ * See ADR-0043. */
6
+ .atl-code-block,
7
+ .atl-code-block * {
8
+ box-sizing: border-box;
9
+ }
10
+
1
11
  /* ============================================================
2
12
  atl-code-block.css
3
13
  ============================================================ */
4
14
 
5
15
  .atl-code-block {
6
16
  display: block;
7
- border: 1px solid var(--ui-color-border);
17
+ border: var(--ui-border-width) solid var(--ui-color-border);
8
18
  border-radius: var(--ui-radius-lg);
9
19
  overflow: hidden;
10
20
  font-family: var(--ui-font-family);
@@ -18,10 +28,19 @@
18
28
  display: flex;
19
29
  align-items: center;
20
30
  justify-content: space-between;
21
- padding: var(--ui-spacing-3) var(--ui-spacing-4);
31
+ /* No block padding: the row is a centred flex line, so `min-height` alone
32
+ * decides the height. Authoring 12+12 around the 0.72rem mono label rendered
33
+ * 43px against a 40px token, and deriving the padding from the label's metrics
34
+ * only moves the guess — the label's line box is not the header's business.
35
+ * See ADR-0047. */
36
+ /* Stated, not inherited: an inherited line-height makes the box grow with the
37
+ * text metrics, which is how three controls measured right on one machine and
38
+ * wrong on another (ADR-0048). */
39
+ line-height: var(--ui-line-height-tight);
40
+ padding: 0 var(--ui-spacing-4);
22
41
  background: var(--ui-color-surface-raised);
23
- border-bottom: 1px solid var(--ui-color-border);
24
- min-height: 2.5rem;
42
+ border-bottom: var(--ui-border-width) solid var(--ui-color-border);
43
+ min-height: var(--ui-control-height-md);
25
44
  }
26
45
 
27
46
  .code-block-label {
@@ -43,7 +62,7 @@
43
62
  align-items: center;
44
63
  gap: 0.3rem;
45
64
  padding: 0.2rem 0.55rem;
46
- border: 1px solid var(--ui-color-border);
65
+ border: var(--ui-border-width) solid var(--ui-color-border);
47
66
  border-radius: var(--ui-radius-sm);
48
67
  background: transparent;
49
68
  color: var(--ui-color-text-muted);
@@ -101,7 +120,7 @@
101
120
  color: var(--ui-color-text-muted);
102
121
  text-align: right;
103
122
  user-select: none;
104
- border-right: 1px solid var(--ui-color-border);
123
+ border-right: var(--ui-border-width) solid var(--ui-color-border);
105
124
  margin-right: var(--ui-spacing-3);
106
125
  flex-shrink: 0;
107
126
  opacity: 0.6;
@@ -1 +1 @@
1
- {"version":3,"file":"atl-code-block.d.ts","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/code-block/atl-code-block.tsx"],"names":[],"mappings":"AACA,OAAO,sBAAsB,CAAC;AAE9B,MAAM,WAAW,iBAAiB;IAChC,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,sEAAsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,0DAA0D;IAC1D,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,wBAAgB,YAAY,CAAC,EAC3B,IAAI,EACJ,QAAiB,EACjB,QAAQ,EACR,QAAe,EACf,eAAuB,GACxB,EAAE,iBAAiB,+BA2DnB"}
1
+ {"version":3,"file":"atl-code-block.d.ts","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/code-block/atl-code-block.tsx"],"names":[],"mappings":"AACA,OAAO,sBAAsB,CAAC;AAG9B,MAAM,WAAW,iBAAiB;IAChC,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,sEAAsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,0DAA0D;IAC1D,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,wBAAgB,YAAY,CAAC,EAC3B,IAAI,EACJ,QAAiB,EACjB,QAAQ,EACR,QAAe,EACf,eAAuB,GACxB,EAAE,iBAAiB,+BAsDnB"}
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useState } from 'react';
3
3
  import './atl-code-block.css';
4
+ import { AtlIcon } from '../icon/atl-icon';
4
5
  export function AtlCodeBlock({ code, language = 'text', filename, copyable = true, showLineNumbers = false, }) {
5
6
  const [copied, setCopied] = useState(false);
6
7
  const displayLabel = filename || language;
@@ -11,7 +12,7 @@ export function AtlCodeBlock({ code, language = 'text', filename, copyable = tru
11
12
  setTimeout(() => setCopied(false), 1800);
12
13
  });
13
14
  }
14
- return (_jsxs("div", { className: "atl-code-block", children: [_jsxs("div", { className: "code-block-header", children: [_jsx("span", { className: "code-block-label", children: displayLabel }), copyable && (_jsx("button", { className: "code-block-copy", type: "button", "aria-label": copied ? 'Copied' : 'Copy code', onClick: handleCopy, children: copied ? (_jsxs(_Fragment, { children: [_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: _jsx("polyline", { points: "20 6 9 17 4 12" }) }), "Copied"] })) : (_jsxs(_Fragment, { children: [_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2", ry: "2" }), _jsx("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })] }), "Copy"] })) }))] }), _jsx("div", { className: "code-block-body", children: _jsx("pre", { className: "code-block-pre", children: _jsx("code", { children: showLineNumbers
15
+ return (_jsxs("div", { className: "atl-code-block", children: [_jsxs("div", { className: "code-block-header", children: [_jsx("span", { className: "code-block-label", children: displayLabel }), copyable && (_jsx("button", { className: "code-block-copy", type: "button", "aria-label": copied ? 'Copied' : 'Copy code', onClick: handleCopy, children: copied ? (_jsxs(_Fragment, { children: [_jsx(AtlIcon, { name: "check", size: "sm" }), "Copied"] })) : (_jsxs(_Fragment, { children: [_jsx(AtlIcon, { name: "copy", size: "sm" }), "Copy"] })) }))] }), _jsx("div", { className: "code-block-body", children: _jsx("pre", { className: "code-block-pre", children: _jsx("code", { children: showLineNumbers
15
16
  ? lines.map((line, i) => (_jsxs("span", { className: "code-line", children: [_jsx("span", { className: "code-line-number", children: i + 1 }), _jsx("span", { className: "code-line-text", children: line })] }, i)))
16
17
  : code }) }) })] }));
17
18
  }
@@ -1 +1 @@
1
- {"version":3,"file":"atl-code-block.js","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/code-block/atl-code-block.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,sBAAsB,CAAC;AAe9B,MAAM,UAAU,YAAY,CAAC,EAC3B,IAAI,EACJ,QAAQ,GAAG,MAAM,EACjB,QAAQ,EACR,QAAQ,GAAG,IAAI,EACf,eAAe,GAAG,KAAK,GACL;IAClB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE5C,MAAM,YAAY,GAAG,QAAQ,IAAI,QAAQ,CAAC;IAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAE/B,SAAS,UAAU;QACjB,KAAK,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;YACjD,SAAS,CAAC,IAAI,CAAC,CAAC;YAChB,UAAU,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,CACL,eAAK,SAAS,EAAC,gBAAgB,aAC7B,eAAK,SAAS,EAAC,mBAAmB,aAChC,eAAM,SAAS,EAAC,kBAAkB,YAAE,YAAY,GAAQ,EACvD,QAAQ,IAAI,CACX,iBACE,SAAS,EAAC,iBAAiB,EAC3B,IAAI,EAAC,QAAQ,gBACD,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,EAC3C,OAAO,EAAE,UAAU,YAElB,MAAM,CAAC,CAAC,CAAC,CACR,8BACE,cAAK,KAAK,EAAC,4BAA4B,EAAC,KAAK,EAAC,IAAI,EAAC,MAAM,EAAC,IAAI,EAAC,OAAO,EAAC,WAAW,EAAC,IAAI,EAAC,MAAM,EAAC,MAAM,EAAC,cAAc,EAAC,WAAW,EAAC,KAAK,EAAC,aAAa,EAAC,OAAO,EAAC,cAAc,EAAC,OAAO,iBAAa,MAAM,YACpM,mBAAU,MAAM,EAAC,gBAAgB,GAAG,GAChC,cAEL,CACJ,CAAC,CAAC,CAAC,CACF,8BACE,eAAK,KAAK,EAAC,4BAA4B,EAAC,KAAK,EAAC,IAAI,EAAC,MAAM,EAAC,IAAI,EAAC,OAAO,EAAC,WAAW,EAAC,IAAI,EAAC,MAAM,EAAC,MAAM,EAAC,cAAc,EAAC,WAAW,EAAC,GAAG,EAAC,aAAa,EAAC,OAAO,EAAC,cAAc,EAAC,OAAO,iBAAa,MAAM,aAClM,eAAM,CAAC,EAAC,GAAG,EAAC,CAAC,EAAC,GAAG,EAAC,KAAK,EAAC,IAAI,EAAC,MAAM,EAAC,IAAI,EAAC,EAAE,EAAC,GAAG,EAAC,EAAE,EAAC,GAAG,GAAG,EACzD,eAAM,CAAC,EAAC,yDAAyD,GAAG,IAChE,YAEL,CACJ,GACM,CACV,IACG,EACN,cAAK,SAAS,EAAC,iBAAiB,YAC9B,cAAK,SAAS,EAAC,gBAAgB,YAC7B,yBACG,eAAe;4BACd,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CACrB,gBAAc,SAAS,EAAC,WAAW,aACjC,eAAM,SAAS,EAAC,kBAAkB,YAAE,CAAC,GAAG,CAAC,GAAQ,EACjD,eAAM,SAAS,EAAC,gBAAgB,YAAE,IAAI,GAAQ,KAFrC,CAAC,CAGL,CACR,CAAC;4BACJ,CAAC,CAAC,IAAI,GACH,GACH,GACF,IACF,CACP,CAAC;AACJ,CAAC","sourcesContent":["import { useState } from 'react';\nimport './atl-code-block.css';\n\nexport interface AtlCodeBlockProps {\n /** The code string to display. */\n code: string;\n /** Language label shown in the header. Ignored if filename is set. */\n language?: string;\n /** Optional filename shown in the header instead of the language label. */\n filename?: string;\n /** Whether to show a copy-to-clipboard button. */\n copyable?: boolean;\n /** Whether to display line numbers alongside the code. */\n showLineNumbers?: boolean;\n}\n\nexport function AtlCodeBlock({\n code,\n language = 'text',\n filename,\n copyable = true,\n showLineNumbers = false,\n}: AtlCodeBlockProps) {\n const [copied, setCopied] = useState(false);\n\n const displayLabel = filename || language;\n const lines = code.split('\\n');\n\n function handleCopy() {\n void navigator.clipboard.writeText(code).then(() => {\n setCopied(true);\n setTimeout(() => setCopied(false), 1800);\n });\n }\n\n return (\n <div className=\"atl-code-block\">\n <div className=\"code-block-header\">\n <span className=\"code-block-label\">{displayLabel}</span>\n {copyable && (\n <button\n className=\"code-block-copy\"\n type=\"button\"\n aria-label={copied ? 'Copied' : 'Copy code'}\n onClick={handleCopy}\n >\n {copied ? (\n <>\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n Copied\n </>\n ) : (\n <>\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n <rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\" ry=\"2\" />\n <path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\" />\n </svg>\n Copy\n </>\n )}\n </button>\n )}\n </div>\n <div className=\"code-block-body\">\n <pre className=\"code-block-pre\">\n <code>\n {showLineNumbers\n ? lines.map((line, i) => (\n <span key={i} className=\"code-line\">\n <span className=\"code-line-number\">{i + 1}</span>\n <span className=\"code-line-text\">{line}</span>\n </span>\n ))\n : code}\n </code>\n </pre>\n </div>\n </div>\n );\n}\n"]}
1
+ {"version":3,"file":"atl-code-block.js","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/code-block/atl-code-block.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,sBAAsB,CAAC;AAC9B,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAe3C,MAAM,UAAU,YAAY,CAAC,EAC3B,IAAI,EACJ,QAAQ,GAAG,MAAM,EACjB,QAAQ,EACR,QAAQ,GAAG,IAAI,EACf,eAAe,GAAG,KAAK,GACL;IAClB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE5C,MAAM,YAAY,GAAG,QAAQ,IAAI,QAAQ,CAAC;IAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAE/B,SAAS,UAAU;QACjB,KAAK,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;YACjD,SAAS,CAAC,IAAI,CAAC,CAAC;YAChB,UAAU,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,CACL,eAAK,SAAS,EAAC,gBAAgB,aAC7B,eAAK,SAAS,EAAC,mBAAmB,aAChC,eAAM,SAAS,EAAC,kBAAkB,YAAE,YAAY,GAAQ,EACvD,QAAQ,IAAI,CACX,iBACE,SAAS,EAAC,iBAAiB,EAC3B,IAAI,EAAC,QAAQ,gBACD,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,EAC3C,OAAO,EAAE,UAAU,YAElB,MAAM,CAAC,CAAC,CAAC,CACR,8BACE,KAAC,OAAO,IAAC,IAAI,EAAC,OAAO,EAAC,IAAI,EAAC,IAAI,GAAG,cAEjC,CACJ,CAAC,CAAC,CAAC,CACF,8BACE,KAAC,OAAO,IAAC,IAAI,EAAC,MAAM,EAAC,IAAI,EAAC,IAAI,GAAG,YAEhC,CACJ,GACM,CACV,IACG,EACN,cAAK,SAAS,EAAC,iBAAiB,YAC9B,cAAK,SAAS,EAAC,gBAAgB,YAC7B,yBACG,eAAe;4BACd,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CACrB,gBAAc,SAAS,EAAC,WAAW,aACjC,eAAM,SAAS,EAAC,kBAAkB,YAAE,CAAC,GAAG,CAAC,GAAQ,EACjD,eAAM,SAAS,EAAC,gBAAgB,YAAE,IAAI,GAAQ,KAFrC,CAAC,CAGL,CACR,CAAC;4BACJ,CAAC,CAAC,IAAI,GACH,GACH,GACF,IACF,CACP,CAAC;AACJ,CAAC","sourcesContent":["import { useState } from 'react';\nimport './atl-code-block.css';\nimport { AtlIcon } from '../icon/atl-icon';\n\nexport interface AtlCodeBlockProps {\n /** The code string to display. */\n code: string;\n /** Language label shown in the header. Ignored if filename is set. */\n language?: string;\n /** Optional filename shown in the header instead of the language label. */\n filename?: string;\n /** Whether to show a copy-to-clipboard button. */\n copyable?: boolean;\n /** Whether to display line numbers alongside the code. */\n showLineNumbers?: boolean;\n}\n\nexport function AtlCodeBlock({\n code,\n language = 'text',\n filename,\n copyable = true,\n showLineNumbers = false,\n}: AtlCodeBlockProps) {\n const [copied, setCopied] = useState(false);\n\n const displayLabel = filename || language;\n const lines = code.split('\\n');\n\n function handleCopy() {\n void navigator.clipboard.writeText(code).then(() => {\n setCopied(true);\n setTimeout(() => setCopied(false), 1800);\n });\n }\n\n return (\n <div className=\"atl-code-block\">\n <div className=\"code-block-header\">\n <span className=\"code-block-label\">{displayLabel}</span>\n {copyable && (\n <button\n className=\"code-block-copy\"\n type=\"button\"\n aria-label={copied ? 'Copied' : 'Copy code'}\n onClick={handleCopy}\n >\n {copied ? (\n <>\n <AtlIcon name=\"check\" size=\"sm\" />\n Copied\n </>\n ) : (\n <>\n <AtlIcon name=\"copy\" size=\"sm\" />\n Copy\n </>\n )}\n </button>\n )}\n </div>\n <div className=\"code-block-body\">\n <pre className=\"code-block-pre\">\n <code>\n {showLineNumbers\n ? lines.map((line, i) => (\n <span key={i} className=\"code-line\">\n <span className=\"code-line-number\">{i + 1}</span>\n <span className=\"code-line-text\">{line}</span>\n </span>\n ))\n : code}\n </code>\n </pre>\n </div>\n </div>\n );\n}\n"]}
@@ -1,3 +1,35 @@
1
+ /* Geometry contract: every size this component states is a border-box size.
2
+ * Declared with the component rather than as a global reset, so it ships in the
3
+ * same file as the sizes it governs and no consuming app has to supply one.
4
+ * Gated by check:box-sizing; the resulting boxes are measured by check:geometry.
5
+ * See ADR-0043. */
6
+ :is(
7
+ .atl-combobox,
8
+ .atl-combobox-check,
9
+ .atl-combobox-error-message,
10
+ .atl-combobox-errors,
11
+ .atl-combobox-icon,
12
+ .atl-combobox-input,
13
+ .atl-combobox-no-results,
14
+ .atl-combobox-option,
15
+ .atl-combobox-panel,
16
+ .atl-combobox-wrapper
17
+ ),
18
+ :is(
19
+ .atl-combobox,
20
+ .atl-combobox-check,
21
+ .atl-combobox-error-message,
22
+ .atl-combobox-errors,
23
+ .atl-combobox-icon,
24
+ .atl-combobox-input,
25
+ .atl-combobox-no-results,
26
+ .atl-combobox-option,
27
+ .atl-combobox-panel,
28
+ .atl-combobox-wrapper
29
+ ) * {
30
+ box-sizing: border-box;
31
+ }
32
+
1
33
  /* ============================================================
2
34
  atl-combobox.css
3
35
  ============================================================ */
@@ -20,14 +52,25 @@
20
52
 
21
53
  .atl-combobox-input {
22
54
  width: 100%;
23
- min-height: 2.5rem;
55
+ min-height: var(--ui-control-height-md);
24
56
  box-sizing: border-box;
25
- padding: 0.625rem var(--ui-spacing-8) 0.625rem var(--ui-spacing-4);
57
+ /* Control line-height plus padding derived from the height, so the box does not
58
+ * depend on which font is installed. Authored 0.625rem padding with an inherited
59
+ * line-height rendered 40px with Instrument Sans and 41px with the fallback — the
60
+ * defect only appeared in CI. See ADR-0048. */
61
+ line-height: var(--ui-line-height-tight);
62
+ padding: calc(
63
+ (var(--ui-control-height-md) - var(--ui-line-height-tight) * var(--ui-font-size-md)) / 2 -
64
+ var(--ui-border-width)
65
+ ) var(--ui-spacing-8) calc(
66
+ (var(--ui-control-height-md) - var(--ui-line-height-tight) * var(--ui-font-size-md)) / 2 -
67
+ var(--ui-border-width)
68
+ ) var(--ui-spacing-4);
26
69
  font-family: inherit;
27
70
  font-size: inherit;
28
71
  color: var(--ui-color-text);
29
72
  background-color: var(--ui-color-input-bg);
30
- border: 1px solid var(--ui-color-input-border);
73
+ border: var(--ui-border-width) solid var(--ui-color-input-border);
31
74
  border-radius: var(--ui-radius-md);
32
75
  outline: none;
33
76
  transition:
@@ -99,10 +142,10 @@
99
142
  margin: 0;
100
143
  padding: var(--ui-spacing-2) 0;
101
144
  background-color: var(--ui-color-surface-raised);
102
- border: 1px solid var(--ui-color-border);
145
+ border: var(--ui-border-width) solid var(--ui-color-border);
103
146
  border-radius: var(--ui-radius-md);
104
147
  box-shadow: var(--ui-shadow-lg);
105
- z-index: 100;
148
+ z-index: var(--ui-z-dropdown);
106
149
  list-style: none;
107
150
  }
108
151
 
@@ -167,3 +210,11 @@
167
210
  color: var(--ui-color-error-text);
168
211
  line-height: var(--ui-line-height-normal);
169
212
  }
213
+
214
+ /* Readonly state — content, not a control: the interactive edge goes away while
215
+ * the filled surface stays. Transparent rather than removed so the 1px border
216
+ * keeps its space and the height stays put (ADR-0045). */
217
+ .atl-combobox.is-readonly .atl-combobox-input {
218
+ border-color: transparent;
219
+ cursor: default;
220
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"atl-combobox.d.ts","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/combobox/atl-combobox.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,oBAAoB,CAAC;AAE5B,YAAY,EAAE,iBAAiB,EAAE,CAAC;AAElC,MAAM,WAAW,gBAAiB,SAAQ,eAAe;IACvD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CAAC,EAC1B,KAAU,EACV,aAAa,EACb,OAAY,EACZ,WAAgB,EAChB,QAAgB,EAChB,QAAgB,EAChB,OAAe,EACf,QAAgB,EAChB,IAAI,EACJ,MAAW,GACZ,EAAE,gBAAgB,+BA2MlB"}
1
+ {"version":3,"file":"atl-combobox.d.ts","sourceRoot":"","sources":["../../../../../../libs/react/src/lib/combobox/atl-combobox.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,oBAAoB,CAAC;AAG5B,YAAY,EAAE,iBAAiB,EAAE,CAAC;AAElC,MAAM,WAAW,gBAAiB,SAAQ,eAAe;IACvD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CAAC,EAC1B,KAAU,EACV,aAAa,EACb,OAAY,EACZ,WAAgB,EAChB,QAAgB,EAChB,QAAgB,EAChB,OAAe,EACf,QAAgB,EAChB,IAAI,EACJ,MAAW,GACZ,EAAE,gBAAgB,+BAwMlB"}
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useEffect, useId, useMemo, useRef, useState } from 'react';
3
3
  import './atl-combobox.css';
4
+ import { AtlIcon } from '../icon/atl-icon';
4
5
  /**
5
6
  * Filterable autocomplete combobox. Accepts an `options` array and emits the
6
7
  * selected option's `value`. The user types to narrow the list; selecting an
@@ -122,18 +123,19 @@ export function AtlCombobox({ value = '', onValueChange, options = [], placehold
122
123
  'atl-combobox',
123
124
  isOpen && 'is-open',
124
125
  disabled && 'is-disabled',
126
+ readonly && 'is-readonly',
125
127
  invalid && 'is-invalid',
126
128
  ]
127
129
  .filter(Boolean)
128
130
  .join(' ');
129
131
  const activeOptionId = activeIndex >= 0 ? `${panelId}-option-${activeIndex}` : undefined;
130
- return (_jsxs("div", { className: classes, ref: containerRef, children: [_jsxs("div", { className: "atl-combobox-wrapper", children: [_jsx("input", { ref: inputRef, className: "atl-combobox-input", type: "text", autoComplete: "off", role: "combobox", id: inputId, "aria-expanded": isOpen, "aria-controls": panelId, "aria-autocomplete": "list", "aria-activedescendant": activeOptionId, "aria-invalid": invalid || undefined, disabled: disabled, readOnly: readonly, required: required, name: name, placeholder: placeholder, value: displayValue, onChange: handleInput, onFocus: handleFocus, onBlur: handleBlur, onKeyDown: handleKeydown }), _jsx("span", { className: "atl-combobox-icon", "aria-hidden": "true", children: _jsx("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", children: _jsx("path", { d: "M2 4l4 4 4-4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }) })] }), isOpen && (_jsx("ul", { id: panelId, className: "atl-combobox-panel", role: "listbox", "aria-labelledby": inputId, children: filteredOptions.length > 0 ? (filteredOptions.map((option, i) => (_jsxs("li", { id: `${panelId}-option-${i}`, role: "option", className: [
132
+ return (_jsxs("div", { className: classes, ref: containerRef, children: [_jsxs("div", { className: "atl-combobox-wrapper", children: [_jsx("input", { ref: inputRef, className: "atl-combobox-input", type: "text", autoComplete: "off", role: "combobox", id: inputId, "aria-expanded": isOpen, "aria-controls": panelId, "aria-autocomplete": "list", "aria-activedescendant": activeOptionId, "aria-invalid": invalid || undefined, disabled: disabled, readOnly: readonly, required: required, name: name, placeholder: placeholder, value: displayValue, onChange: handleInput, onFocus: handleFocus, onBlur: handleBlur, onKeyDown: handleKeydown }), _jsx("span", { className: "atl-combobox-icon", "aria-hidden": "true", children: _jsx(AtlIcon, { name: "chevron-down", size: "sm" }) })] }), isOpen && (_jsx("ul", { id: panelId, className: "atl-combobox-panel", role: "listbox", "aria-labelledby": inputId, children: filteredOptions.length > 0 ? (filteredOptions.map((option, i) => (_jsxs("li", { id: `${panelId}-option-${i}`, role: "option", className: [
131
133
  'atl-combobox-option',
132
134
  activeIndex === i && 'is-active',
133
135
  option.value === value && 'is-selected',
134
136
  option.disabled && 'is-disabled',
135
137
  ]
136
138
  .filter(Boolean)
137
- .join(' '), "aria-selected": option.value === value, "aria-disabled": option.disabled || undefined, onMouseDown: () => selectOption(option), onMouseEnter: () => setActiveIndex(i), children: [_jsx("span", { children: option.label }), option.value === value && (_jsx("svg", { className: "atl-combobox-check", width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", "aria-hidden": "true", children: _jsx("path", { d: "M2 7l4 4 6-7", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }))] }, option.value)))) : (_jsx("li", { className: "atl-combobox-no-results", role: "option", "aria-selected": false, "aria-disabled": "true", children: "No results found." })) })), invalid && errors.length > 0 && (_jsx("div", { className: "atl-combobox-errors", role: "alert", "aria-live": "polite", children: errors.map((e, i) => (_jsx("p", { className: "atl-combobox-error-message", children: e }, i))) }))] }));
139
+ .join(' '), "aria-selected": option.value === value, "aria-disabled": option.disabled || undefined, onMouseDown: () => selectOption(option), onMouseEnter: () => setActiveIndex(i), children: [_jsx("span", { children: option.label }), option.value === value && (_jsx(AtlIcon, { name: "check", size: "sm", className: "atl-combobox-check" }))] }, option.value)))) : (_jsx("li", { className: "atl-combobox-no-results", role: "option", "aria-selected": false, "aria-disabled": "true", children: "No results found." })) })), invalid && errors.length > 0 && (_jsx("div", { className: "atl-combobox-errors", role: "alert", "aria-live": "polite", children: errors.map((e, i) => (_jsx("p", { className: "atl-combobox-error-message", children: e }, i))) }))] }));
138
140
  }
139
141
  //# sourceMappingURL=atl-combobox.js.map