@atelier-ui/react 0.2.14 → 0.2.16
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.
- package/CHANGELOG.md +29 -0
- package/package.json +1 -1
- package/src/lib/accordion/atl-accordion.css +21 -5
- package/src/lib/accordion/atl-accordion.d.ts.map +1 -1
- package/src/lib/accordion/atl-accordion.js +2 -3
- package/src/lib/accordion/atl-accordion.js.map +1 -1
- package/src/lib/alert/atl-alert.css +11 -1
- package/src/lib/alert/atl-alert.d.ts.map +1 -1
- package/src/lib/alert/atl-alert.js +2 -1
- package/src/lib/alert/atl-alert.js.map +1 -1
- package/src/lib/avatar/atl-avatar.css +24 -4
- package/src/lib/avatar/atl-avatar.d.ts.map +1 -1
- package/src/lib/avatar/atl-avatar.js +2 -1
- package/src/lib/avatar/atl-avatar.js.map +1 -1
- package/src/lib/badge/atl-badge.css +16 -6
- package/src/lib/breadcrumbs/atl-breadcrumbs.css +16 -0
- package/src/lib/button/atl-button.css +12 -2
- package/src/lib/card/atl-card.css +29 -4
- package/src/lib/chat/atl-chat.css +44 -15
- package/src/lib/chat/atl-chat.d.ts.map +1 -1
- package/src/lib/chat/atl-chat.js +2 -1
- package/src/lib/chat/atl-chat.js.map +1 -1
- package/src/lib/checkbox/atl-checkbox.css +12 -2
- package/src/lib/checkbox/atl-checkbox.d.ts +1 -5
- package/src/lib/checkbox/atl-checkbox.d.ts.map +1 -1
- package/src/lib/checkbox/atl-checkbox.js +2 -3
- package/src/lib/checkbox/atl-checkbox.js.map +1 -1
- package/src/lib/code-block/atl-code-block.css +27 -8
- package/src/lib/code-block/atl-code-block.d.ts.map +1 -1
- package/src/lib/code-block/atl-code-block.js +2 -1
- package/src/lib/code-block/atl-code-block.js.map +1 -1
- package/src/lib/combobox/atl-combobox.css +56 -5
- package/src/lib/combobox/atl-combobox.d.ts.map +1 -1
- package/src/lib/combobox/atl-combobox.js +4 -2
- package/src/lib/combobox/atl-combobox.js.map +1 -1
- package/src/lib/dialog/atl-dialog.css +28 -4
- package/src/lib/dialog/atl-dialog.d.ts.map +1 -1
- package/src/lib/dialog/atl-dialog.js +2 -1
- package/src/lib/dialog/atl-dialog.js.map +1 -1
- package/src/lib/drawer/atl-drawer.css +31 -4
- package/src/lib/drawer/atl-drawer.d.ts.map +1 -1
- package/src/lib/drawer/atl-drawer.js +2 -1
- package/src/lib/drawer/atl-drawer.js.map +1 -1
- package/src/lib/icon/atl-icon.css +18 -0
- package/src/lib/icon/atl-icon.d.ts +2 -1
- package/src/lib/icon/atl-icon.d.ts.map +1 -1
- package/src/lib/icon/atl-icon.js +6 -25
- package/src/lib/icon/atl-icon.js.map +1 -1
- package/src/lib/icons.d.ts +39 -0
- package/src/lib/icons.d.ts.map +1 -0
- package/src/lib/icons.js +49 -0
- package/src/lib/icons.js.map +1 -0
- package/src/lib/input/atl-input.css +21 -7
- package/src/lib/input/atl-input.d.ts.map +1 -1
- package/src/lib/input/atl-input.js +2 -1
- package/src/lib/input/atl-input.js.map +1 -1
- package/src/lib/menu/atl-menu.css +28 -3
- package/src/lib/pagination/atl-pagination.css +11 -1
- package/src/lib/progress/atl-progress.css +10 -0
- package/src/lib/radio/atl-radio.css +11 -1
- package/src/lib/radio/atl-radio.d.ts.map +1 -1
- package/src/lib/radio/atl-radio.js +5 -3
- package/src/lib/radio/atl-radio.js.map +1 -1
- package/src/lib/radio-group/atl-radio-group.css +10 -0
- package/src/lib/select/atl-select.css +21 -3
- package/src/lib/select/atl-select.d.ts +1 -5
- package/src/lib/select/atl-select.d.ts.map +1 -1
- package/src/lib/select/atl-select.js +1 -3
- package/src/lib/select/atl-select.js.map +1 -1
- package/src/lib/skeleton/atl-skeleton.css +15 -0
- package/src/lib/spec.d.ts +20 -6
- package/src/lib/spec.d.ts.map +1 -1
- package/src/lib/spec.js +1 -1
- package/src/lib/spec.js.map +1 -1
- package/src/lib/stepper/atl-stepper.css +11 -1
- package/src/lib/stepper/atl-stepper.d.ts.map +1 -1
- package/src/lib/stepper/atl-stepper.js +2 -1
- package/src/lib/stepper/atl-stepper.js.map +1 -1
- package/src/lib/table/atl-table.css +42 -3
- package/src/lib/table/atl-table.d.ts.map +1 -1
- package/src/lib/table/atl-table.js +2 -1
- package/src/lib/table/atl-table.js.map +1 -1
- package/src/lib/tabs/atl-tabs.css +27 -5
- package/src/lib/textarea/atl-textarea.css +22 -7
- package/src/lib/textarea/atl-textarea.d.ts.map +1 -1
- package/src/lib/textarea/atl-textarea.js +2 -1
- package/src/lib/textarea/atl-textarea.js.map +1 -1
- package/src/lib/toast/atl-toast.css +21 -0
- package/src/lib/toast/atl-toast.d.ts.map +1 -1
- package/src/lib/toast/atl-toast.js +2 -1
- package/src/lib/toast/atl-toast.js.map +1 -1
- package/src/lib/toggle/atl-toggle.css +11 -1
- package/src/lib/toggle/atl-toggle.d.ts +1 -5
- package/src/lib/toggle/atl-toggle.d.ts.map +1 -1
- package/src/lib/toggle/atl-toggle.js +2 -3
- package/src/lib/toggle/atl-toggle.js.map +1 -1
- package/src/lib/tooltip/atl-tooltip.css +21 -0
- package/styles/tokens.css +12 -0
|
@@ -1,5 +1,36 @@
|
|
|
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 {
|
|
29
|
+
/* The library states its own typeface (ADR-0035). Without this the component
|
|
30
|
+
* renders in the consuming app's font while its neighbours render Instrument
|
|
31
|
+
* Sans — measured: a card next to a button showed two typefaces. Declared once
|
|
32
|
+
* per component root, never on a descendant (ADR-0049). */
|
|
33
|
+
font-family: var(--ui-font-family);
|
|
3
34
|
display: contents;
|
|
4
35
|
}
|
|
5
36
|
|
|
@@ -17,6 +48,8 @@
|
|
|
17
48
|
/* ═══════════════════════════════════════════════════════════════════════════ */
|
|
18
49
|
.atl-chat.variant-drawer dialog {
|
|
19
50
|
all: unset;
|
|
51
|
+
/* After `all: unset`, which would otherwise reset it (ADR-0049). */
|
|
52
|
+
font-family: var(--ui-font-family);
|
|
20
53
|
position: fixed;
|
|
21
54
|
inset: 0 0 0 auto;
|
|
22
55
|
height: 100dvh;
|
|
@@ -70,7 +103,7 @@
|
|
|
70
103
|
height: 35rem;
|
|
71
104
|
border-radius: var(--ui-radius-xl);
|
|
72
105
|
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.18);
|
|
73
|
-
z-index:
|
|
106
|
+
z-index: var(--ui-z-dropdown);
|
|
74
107
|
}
|
|
75
108
|
|
|
76
109
|
.atl-chat.variant-popup .fab-bubble {
|
|
@@ -83,7 +116,6 @@
|
|
|
83
116
|
background: var(--ui-color-brand-ai, #b5e61c);
|
|
84
117
|
color: var(--ui-color-text);
|
|
85
118
|
border: none;
|
|
86
|
-
font-family: var(--ui-font-family);
|
|
87
119
|
font-size: var(--ui-font-size-lg);
|
|
88
120
|
font-weight: var(--ui-font-weight-semibold);
|
|
89
121
|
cursor: pointer;
|
|
@@ -111,7 +143,7 @@
|
|
|
111
143
|
width: 100%;
|
|
112
144
|
height: 100%;
|
|
113
145
|
min-height: 24rem;
|
|
114
|
-
border:
|
|
146
|
+
border: var(--ui-border-width) solid var(--ui-color-border);
|
|
115
147
|
border-radius: var(--ui-radius-xl);
|
|
116
148
|
}
|
|
117
149
|
|
|
@@ -128,7 +160,7 @@
|
|
|
128
160
|
justify-content: space-between;
|
|
129
161
|
gap: var(--ui-spacing-3);
|
|
130
162
|
padding: var(--ui-spacing-3) var(--ui-spacing-4);
|
|
131
|
-
border-bottom:
|
|
163
|
+
border-bottom: var(--ui-border-width) solid var(--ui-color-border);
|
|
132
164
|
flex-shrink: 0;
|
|
133
165
|
}
|
|
134
166
|
|
|
@@ -149,11 +181,11 @@
|
|
|
149
181
|
align-items: center;
|
|
150
182
|
justify-content: center;
|
|
151
183
|
flex-shrink: 0;
|
|
152
|
-
width:
|
|
153
|
-
height:
|
|
184
|
+
width: var(--ui-control-height-sm);
|
|
185
|
+
height: var(--ui-control-height-sm);
|
|
154
186
|
padding: 0;
|
|
155
187
|
background: transparent;
|
|
156
|
-
border:
|
|
188
|
+
border: var(--ui-border-width) solid var(--ui-color-border);
|
|
157
189
|
border-radius: var(--ui-radius-sm);
|
|
158
190
|
cursor: pointer;
|
|
159
191
|
color: var(--ui-color-text-muted);
|
|
@@ -220,7 +252,7 @@
|
|
|
220
252
|
|
|
221
253
|
.atl-chat-message.is-failed {
|
|
222
254
|
background: var(--ui-color-surface-sunken);
|
|
223
|
-
border:
|
|
255
|
+
border: var(--ui-border-width) dashed var(--ui-color-danger);
|
|
224
256
|
color: var(--ui-color-text);
|
|
225
257
|
}
|
|
226
258
|
|
|
@@ -310,9 +342,8 @@
|
|
|
310
342
|
padding: var(--ui-spacing-3) var(--ui-spacing-4);
|
|
311
343
|
background: var(--ui-color-surface);
|
|
312
344
|
color: var(--ui-color-text);
|
|
313
|
-
border:
|
|
345
|
+
border: var(--ui-border-width) solid var(--ui-color-border);
|
|
314
346
|
border-radius: var(--ui-radius-lg);
|
|
315
|
-
font-family: var(--ui-font-family);
|
|
316
347
|
text-align: left;
|
|
317
348
|
cursor: pointer;
|
|
318
349
|
transition:
|
|
@@ -349,7 +380,7 @@
|
|
|
349
380
|
align-items: flex-end;
|
|
350
381
|
gap: var(--ui-spacing-2);
|
|
351
382
|
padding: var(--ui-spacing-3) var(--ui-spacing-4);
|
|
352
|
-
border-top:
|
|
383
|
+
border-top: var(--ui-border-width) solid var(--ui-color-border);
|
|
353
384
|
background: var(--ui-color-surface);
|
|
354
385
|
flex-shrink: 0;
|
|
355
386
|
}
|
|
@@ -358,11 +389,10 @@
|
|
|
358
389
|
flex: 1;
|
|
359
390
|
min-width: 0;
|
|
360
391
|
padding: var(--ui-spacing-2) var(--ui-spacing-3);
|
|
361
|
-
border:
|
|
392
|
+
border: var(--ui-border-width) solid var(--ui-color-input-border, var(--ui-color-border));
|
|
362
393
|
border-radius: var(--ui-radius-md);
|
|
363
394
|
background: var(--ui-color-surface-sunken);
|
|
364
395
|
color: var(--ui-color-text);
|
|
365
|
-
font-family: var(--ui-font-family);
|
|
366
396
|
font-size: var(--ui-font-size-sm);
|
|
367
397
|
line-height: var(--ui-line-height-normal);
|
|
368
398
|
resize: none;
|
|
@@ -394,9 +424,8 @@
|
|
|
394
424
|
justify-content: center;
|
|
395
425
|
flex-shrink: 0;
|
|
396
426
|
padding: var(--ui-spacing-2) var(--ui-spacing-4);
|
|
397
|
-
border:
|
|
427
|
+
border: var(--ui-border-width) solid transparent;
|
|
398
428
|
border-radius: var(--ui-radius-md);
|
|
399
|
-
font-family: var(--ui-font-family);
|
|
400
429
|
font-size: var(--ui-font-size-sm);
|
|
401
430
|
font-weight: var(--ui-font-weight-medium);
|
|
402
431
|
cursor: pointer;
|
|
@@ -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;
|
|
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"}
|
package/src/lib/chat/atl-chat.js
CHANGED
|
@@ -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:
|
|
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":"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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';\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:
|
|
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:
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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;
|
|
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:
|
|
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,14 +28,23 @@
|
|
|
18
28
|
display: flex;
|
|
19
29
|
align-items: center;
|
|
20
30
|
justify-content: space-between;
|
|
21
|
-
padding:
|
|
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:
|
|
24
|
-
min-height:
|
|
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 {
|
|
28
|
-
font-family: var(--ui-font-mono
|
|
47
|
+
font-family: var(--ui-font-mono);
|
|
29
48
|
font-size: 0.72rem;
|
|
30
49
|
font-weight: 600;
|
|
31
50
|
letter-spacing: 0.03em;
|
|
@@ -43,7 +62,7 @@
|
|
|
43
62
|
align-items: center;
|
|
44
63
|
gap: 0.3rem;
|
|
45
64
|
padding: 0.2rem 0.55rem;
|
|
46
|
-
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);
|
|
@@ -78,7 +97,7 @@
|
|
|
78
97
|
.code-block-pre {
|
|
79
98
|
margin: 0;
|
|
80
99
|
padding: var(--ui-spacing-4);
|
|
81
|
-
font-family: var(--ui-font-mono
|
|
100
|
+
font-family: var(--ui-font-mono);
|
|
82
101
|
font-size: var(--ui-font-size-sm);
|
|
83
102
|
line-height: 1.65;
|
|
84
103
|
color: var(--ui-color-text);
|
|
@@ -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:
|
|
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;
|
|
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(
|
|
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;
|
|
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:
|
|
55
|
+
min-height: var(--ui-control-height-md);
|
|
24
56
|
box-sizing: border-box;
|
|
25
|
-
|
|
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:
|
|
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:
|
|
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:
|
|
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;
|
|
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"}
|