@agentero/design-system 0.32.0 → 0.32.2
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/mcp/manifests/components.html +108 -54
- package/mcp/manifests/components.json +51 -13
- package/package.json +1 -1
- package/src/accordion/accordion.js +1 -1
- package/src/avatar/avatar.js +46 -41
- package/src/button/button.js +1 -1
- package/src/checkbox/checkbox.js +1 -1
- package/src/combobox/combobox.d.ts +91 -28
- package/src/combobox/combobox.js +96 -65
- package/src/combobox/icons.d.ts +16 -0
- package/src/combobox/icons.js +19 -1
- package/src/combobox/index.d.ts +6 -2
- package/src/data-table/data-table.js +1 -1
- package/src/dropdown-menu/dropdown-menu.js +16 -22
- package/src/hover-card/hover-card.js +2 -2
- package/src/progress/progress.js +1 -1
- package/src/switch/switch.js +1 -1
- package/src/table/table.js +1 -1
- package/src/tabs/tabs.js +2 -2
- package/src/tooltip/tooltip.js +4 -4
- package/theme/base.css +24 -18
|
@@ -588,13 +588,13 @@
|
|
|
588
588
|
<header>
|
|
589
589
|
<div class="wrap">
|
|
590
590
|
<h1>Manifest Debugger</h1>
|
|
591
|
-
<div class="summary"><a class="filter-pill all" data-k="all" href="#filter-all">All</a><span class="filter-pill ok" aria-disabled="true">34 components ok</span><span class="filter-pill ok" aria-disabled="true">
|
|
591
|
+
<div class="summary"><a class="filter-pill all" data-k="all" href="#filter-all">All</a><span class="filter-pill ok" aria-disabled="true">34 components ok</span><span class="filter-pill ok" aria-disabled="true">281 stories ok</span></div>
|
|
592
592
|
</div>
|
|
593
593
|
</header>
|
|
594
594
|
<main>
|
|
595
595
|
<div class="wrap">
|
|
596
596
|
<div class="note ok" style="margin-bottom: 16px;">
|
|
597
|
-
Using <code>react-component-meta</code>. Generation took <strong>
|
|
597
|
+
Using <code>react-component-meta</code>. Generation took <strong>4.9s</strong>.
|
|
598
598
|
</div>
|
|
599
599
|
<h2 class="section-title">Components</h2>
|
|
600
600
|
<div class="grid" role="list">
|
|
@@ -1562,7 +1562,7 @@ variant?: "circle" | "square" | "pillow" | "p
|
|
|
1562
1562
|
<div class="row">
|
|
1563
1563
|
<span class="ex-name">Imports</span>
|
|
1564
1564
|
</div>
|
|
1565
|
-
<pre><code>import { Avatar } from "@agentero/design-system";</code></pre>
|
|
1565
|
+
<pre><code>import { Avatar, Button } from "@agentero/design-system";</code></pre>
|
|
1566
1566
|
</div>
|
|
1567
1567
|
|
|
1568
1568
|
|
|
@@ -2855,9 +2855,9 @@ import { CheckList } from '@agentero/design-system/check-list';
|
|
|
2855
2855
|
<div class="title">
|
|
2856
2856
|
<h2><span class="status-dot dot-ok"></span> Combobox.Root</h2>
|
|
2857
2857
|
<div class="badges">
|
|
2858
|
-
<label for="c-7-components-combobox-props" class="badge ok as-toggle">
|
|
2858
|
+
<label for="c-7-components-combobox-props" class="badge ok as-toggle">39 prop types</label>
|
|
2859
2859
|
|
|
2860
|
-
<label for="c-7-components-combobox-stories" class="badge ok as-toggle">
|
|
2860
|
+
<label for="c-7-components-combobox-stories" class="badge ok as-toggle">10 stories</label>
|
|
2861
2861
|
|
|
2862
2862
|
|
|
2863
2863
|
</div>
|
|
@@ -2900,7 +2900,7 @@ import { Combobox } from '@agentero/design-system/combobox';
|
|
|
2900
2900
|
<div class="note ok">
|
|
2901
2901
|
<div class="row">
|
|
2902
2902
|
<span class="ex-name">Prop types <small>(react-component-meta)</small></span>
|
|
2903
|
-
<span class="badge ok">
|
|
2903
|
+
<span class="badge ok">39 prop types</span>
|
|
2904
2904
|
</div>
|
|
2905
2905
|
<pre><code>Component: src/combobox/index.ts::Combobox</code></pre>
|
|
2906
2906
|
<pre><code>Props:</code></pre>
|
|
@@ -3060,6 +3060,14 @@ locale?: LocalesArgument
|
|
|
3060
3060
|
*/
|
|
3061
3061
|
loopFocus?: boolean = true
|
|
3062
3062
|
|
|
3063
|
+
/**
|
|
3064
|
+
* Characters the query needs, spaces aside, before the list opens. Below it
|
|
3065
|
+
* focusing, clicking or pressing the chevron leaves the list shut, and
|
|
3066
|
+
* deleting back under it closes the list. Defaults to `0`: the list opens on
|
|
3067
|
+
* focus.
|
|
3068
|
+
*/
|
|
3069
|
+
minInputLength?: number = 0
|
|
3070
|
+
|
|
3063
3071
|
/**
|
|
3064
3072
|
* Determines if the popup enters a modal state when open.
|
|
3065
3073
|
* - `true`: user interaction is limited to the popup: document page scroll is locked and pointer interactions on outside elements are disabled.
|
|
@@ -3149,17 +3157,7 @@ virtualized?: boolean = false</code></pre>
|
|
|
3149
3157
|
<div class="row">
|
|
3150
3158
|
<span class="ex-name">Imports</span>
|
|
3151
3159
|
</div>
|
|
3152
|
-
<pre><code>import {
|
|
3153
|
-
Button,
|
|
3154
|
-
Combobox,
|
|
3155
|
-
Field,
|
|
3156
|
-
FieldText,
|
|
3157
|
-
IconSearch,
|
|
3158
|
-
Label,
|
|
3159
|
-
Modal,
|
|
3160
|
-
Skeleton,
|
|
3161
|
-
Tag,
|
|
3162
|
-
} from "@agentero/design-system";
|
|
3160
|
+
<pre><code>import { Button, Combobox, Field, FieldText, Label, Modal, Skeleton, Tag } from "@agentero/design-system";
|
|
3163
3161
|
import { Suspense } from "react";</code></pre>
|
|
3164
3162
|
</div>
|
|
3165
3163
|
|
|
@@ -3169,9 +3167,11 @@ import { Suspense } from "react";</code></pre>
|
|
|
3169
3167
|
<span class="ex-name">Default</span>
|
|
3170
3168
|
<span class="badge ok">story ok</span>
|
|
3171
3169
|
</div>
|
|
3172
|
-
|
|
3170
|
+
<div>Search field with a magnifier and clear button over an in-memory list</div>
|
|
3173
3171
|
<div class="hint">The common case: options are already in memory and Base UI filters them against
|
|
3174
|
-
what you type. Selecting a row fills the input and closes the list
|
|
3172
|
+
what you type. Selecting a row fills the input and closes the list. The field is
|
|
3173
|
+
a search out of the box — a magnifier in front, a clear button once something is
|
|
3174
|
+
picked — and the list hangs from the whole field.</div>
|
|
3175
3175
|
<pre><code>const Default = () => (
|
|
3176
3176
|
<Combobox.Root items={STATES}>
|
|
3177
3177
|
<Combobox.Input placeholder="Search states" aria-label="Search states" />
|
|
@@ -3186,6 +3186,83 @@ what you type. Selecting a row fills the input and closes the list.</div>
|
|
|
3186
3186
|
</Combobox.List>
|
|
3187
3187
|
</Combobox.Content>
|
|
3188
3188
|
</Combobox.Root>
|
|
3189
|
+
);</code></pre>
|
|
3190
|
+
</div>
|
|
3191
|
+
<div class="note ok">
|
|
3192
|
+
<div class="row">
|
|
3193
|
+
<span class="ex-name">Plain</span>
|
|
3194
|
+
<span class="badge ok">story ok</span>
|
|
3195
|
+
</div>
|
|
3196
|
+
<div>Bare input with no icon and no clear button</div>
|
|
3197
|
+
<div class="hint">`variant="plain"`: the input alone, with no magnifier and no clear button, for a
|
|
3198
|
+
field that needs no affordance — a FEIN lookup, a template name. The list still
|
|
3199
|
+
matches the field's width.</div>
|
|
3200
|
+
<pre><code>const Plain = () => (
|
|
3201
|
+
<Combobox.Root items={STATES}>
|
|
3202
|
+
<Combobox.Input variant="plain" placeholder="State" aria-label="State" />
|
|
3203
|
+
<Combobox.Content>
|
|
3204
|
+
<Combobox.Empty>No matches found</Combobox.Empty>
|
|
3205
|
+
<Combobox.List>
|
|
3206
|
+
{(state: string) => (
|
|
3207
|
+
<Combobox.Item key={state} value={state}>
|
|
3208
|
+
{state}
|
|
3209
|
+
</Combobox.Item>
|
|
3210
|
+
)}
|
|
3211
|
+
</Combobox.List>
|
|
3212
|
+
</Combobox.Content>
|
|
3213
|
+
</Combobox.Root>
|
|
3214
|
+
);</code></pre>
|
|
3215
|
+
</div>
|
|
3216
|
+
<div class="note ok">
|
|
3217
|
+
<div class="row">
|
|
3218
|
+
<span class="ex-name">Select</span>
|
|
3219
|
+
<span class="badge ok">story ok</span>
|
|
3220
|
+
</div>
|
|
3221
|
+
<div>Field with a chevron that toggles the list, for short known lists</div>
|
|
3222
|
+
<div class="hint">`variant="select"`: a chevron after the input opens and closes the list, for a
|
|
3223
|
+
short known list the user may want to browse before typing. It has no clear
|
|
3224
|
+
button by default. The chevron is out of the tab order — the input already
|
|
3225
|
+
opens the list from the keyboard with the arrow keys.</div>
|
|
3226
|
+
<pre><code>const Select = () => (
|
|
3227
|
+
<Combobox.Root items={STATES}>
|
|
3228
|
+
<Combobox.Input variant="select" placeholder="Choose a state" aria-label="State" />
|
|
3229
|
+
<Combobox.Content>
|
|
3230
|
+
<Combobox.Empty>No matches found</Combobox.Empty>
|
|
3231
|
+
<Combobox.List>
|
|
3232
|
+
{(state: string) => (
|
|
3233
|
+
<Combobox.Item key={state} value={state}>
|
|
3234
|
+
{state}
|
|
3235
|
+
</Combobox.Item>
|
|
3236
|
+
)}
|
|
3237
|
+
</Combobox.List>
|
|
3238
|
+
</Combobox.Content>
|
|
3239
|
+
</Combobox.Root>
|
|
3240
|
+
);</code></pre>
|
|
3241
|
+
</div>
|
|
3242
|
+
<div class="note ok">
|
|
3243
|
+
<div class="row">
|
|
3244
|
+
<span class="ex-name">Select With Clear</span>
|
|
3245
|
+
<span class="badge ok">story ok</span>
|
|
3246
|
+
</div>
|
|
3247
|
+
<div>Select field with a clear button added through showClear</div>
|
|
3248
|
+
<div class="hint">`showClear` overrides the variant's default: here it adds the clear button to a
|
|
3249
|
+
`select`, so a picked option can be removed without selecting the text and
|
|
3250
|
+
deleting it. While there is a value it takes the chevron's place; clearing
|
|
3251
|
+
brings the chevron back. Passing `false` drops it from `search`.</div>
|
|
3252
|
+
<pre><code>const SelectWithClear = () => (
|
|
3253
|
+
<Combobox.Root items={STATES} defaultValue="Florida">
|
|
3254
|
+
<Combobox.Input variant="select" showClear placeholder="Choose a state" aria-label="State" />
|
|
3255
|
+
<Combobox.Content>
|
|
3256
|
+
<Combobox.Empty>No matches found</Combobox.Empty>
|
|
3257
|
+
<Combobox.List>
|
|
3258
|
+
{(state: string) => (
|
|
3259
|
+
<Combobox.Item key={state} value={state}>
|
|
3260
|
+
{state}
|
|
3261
|
+
</Combobox.Item>
|
|
3262
|
+
)}
|
|
3263
|
+
</Combobox.List>
|
|
3264
|
+
</Combobox.Content>
|
|
3265
|
+
</Combobox.Root>
|
|
3189
3266
|
);</code></pre>
|
|
3190
3267
|
</div>
|
|
3191
3268
|
<div class="note ok">
|
|
@@ -3294,11 +3371,15 @@ out-of-order responses harmless. Drop a `useSuspenseQuery` where `use()` is.</di
|
|
|
3294
3371
|
<span class="ex-name">Async Search With Status</span>
|
|
3295
3372
|
<span class="badge ok">story ok</span>
|
|
3296
3373
|
</div>
|
|
3297
|
-
|
|
3374
|
+
<div>API search that waits for two characters, with loading status</div>
|
|
3298
3375
|
<div class="hint">The same search without Suspense, for a consumer that gets a `loading` flag from
|
|
3299
3376
|
its data layer instead: `filter={null}`, the rows arrive through `filteredItems`,
|
|
3300
3377
|
`Content` is marked busy and `Status` announces the wait. The list is cleared
|
|
3301
|
-
before each request and a request that is no longer the latest is dropped
|
|
3378
|
+
before each request and a request that is no longer the latest is dropped.
|
|
3379
|
+
|
|
3380
|
+
`minInputLength` keeps the list shut until two characters are typed — focusing
|
|
3381
|
+
the field opens nothing, and deleting back under the minimum closes it — and
|
|
3382
|
+
no request goes out for a shorter query either.</div>
|
|
3302
3383
|
<pre><code>const AsyncSearchWithStatus = () => {
|
|
3303
3384
|
const [results, setResults] = useState<Agency[]>([]);
|
|
3304
3385
|
const [isLoading, setIsLoading] = useState(false);
|
|
@@ -3307,6 +3388,11 @@ before each request and a request that is no longer the latest is dropped.</div>
|
|
|
3307
3388
|
|
|
3308
3389
|
const onInputValueChange = async (query: string) => {
|
|
3309
3390
|
const request = ++latestRequest.current;
|
|
3391
|
+
if (query.trim().length < MIN_QUERY_LENGTH) {
|
|
3392
|
+
setResults([]);
|
|
3393
|
+
setIsLoading(false);
|
|
3394
|
+
return;
|
|
3395
|
+
}
|
|
3310
3396
|
|
|
3311
3397
|
// The previous rows go before the wait starts: a list that no longer matches what is typed
|
|
3312
3398
|
// must not sit under the loading state.
|
|
@@ -3325,6 +3411,7 @@ before each request and a request that is no longer the latest is dropped.</div>
|
|
|
3325
3411
|
items={results}
|
|
3326
3412
|
filteredItems={results}
|
|
3327
3413
|
filter={null}
|
|
3414
|
+
minInputLength={MIN_QUERY_LENGTH}
|
|
3328
3415
|
itemToStringLabel={(agency: Agency) => agency.name}
|
|
3329
3416
|
isItemEqualToValue={(a: Agency, b: Agency) => a.id === b.id}
|
|
3330
3417
|
onInputValueChange={onInputValueChange}>
|
|
@@ -3379,39 +3466,6 @@ rest of the page from assistive technology, label included, and a
|
|
|
3379
3466
|
<Field.Description>The agency this agent will be added to.</Field.Description>
|
|
3380
3467
|
<Field.Error errors={[{ message: 'Pick an agency from the list' }]} />
|
|
3381
3468
|
</FieldText>
|
|
3382
|
-
);</code></pre>
|
|
3383
|
-
</div>
|
|
3384
|
-
<div class="note ok">
|
|
3385
|
-
<div class="row">
|
|
3386
|
-
<span class="ex-name">With Leading Icon</span>
|
|
3387
|
-
<span class="badge ok">story ok</span>
|
|
3388
|
-
</div>
|
|
3389
|
-
|
|
3390
|
-
<div class="hint">A leading icon is composed around the input, not baked in: not every combobox
|
|
3391
|
-
is a search (a FEIN lookup or a template picker are not), so the component
|
|
3392
|
-
ships no icon of its own. Until `InputGroup` lands in the design system, the
|
|
3393
|
-
marketplace search fields get theirs like this — the icon overlaid, the input
|
|
3394
|
-
padded past it.</div>
|
|
3395
|
-
<pre><code>const WithLeadingIcon = () => (
|
|
3396
|
-
<Combobox.Root items={STATES}>
|
|
3397
|
-
<div className="relative">
|
|
3398
|
-
<IconSearch
|
|
3399
|
-
aria-hidden
|
|
3400
|
-
className="pointer-events-none absolute top-1/2 left-3 -z-hide size-6 -translate-y-1/2 [&>path]:fill-icon-default-base-tertiary"
|
|
3401
|
-
/>
|
|
3402
|
-
<Combobox.Input className="pl-11" placeholder="Search states" aria-label="Search states" />
|
|
3403
|
-
</div>
|
|
3404
|
-
<Combobox.Content>
|
|
3405
|
-
<Combobox.Empty>No matches found</Combobox.Empty>
|
|
3406
|
-
<Combobox.List>
|
|
3407
|
-
{(state: string) => (
|
|
3408
|
-
<Combobox.Item key={state} value={state}>
|
|
3409
|
-
{state}
|
|
3410
|
-
</Combobox.Item>
|
|
3411
|
-
)}
|
|
3412
|
-
</Combobox.List>
|
|
3413
|
-
</Combobox.Content>
|
|
3414
|
-
</Combobox.Root>
|
|
3415
3469
|
);</code></pre>
|
|
3416
3470
|
</div>
|
|
3417
3471
|
<div class="note ok">
|
|
@@ -1225,7 +1225,7 @@
|
|
|
1225
1225
|
"summary": "All avatar shapes with a profile image"
|
|
1226
1226
|
}
|
|
1227
1227
|
],
|
|
1228
|
-
"import": "import { Avatar } from \"@agentero/design-system\";"
|
|
1228
|
+
"import": "import { Avatar, Button } from \"@agentero/design-system\";"
|
|
1229
1229
|
},
|
|
1230
1230
|
"components-button": {
|
|
1231
1231
|
"id": "components-button",
|
|
@@ -2007,7 +2007,7 @@
|
|
|
2007
2007
|
"displayName": "Combobox.Root",
|
|
2008
2008
|
"exportName": "Combobox",
|
|
2009
2009
|
"filePath": "/home/runner/work/design-system/design-system/src/combobox/index.ts",
|
|
2010
|
-
"description": "Root of a combobox: a text input that filters a list of options and writes the\nchosen one back into itself.
|
|
2010
|
+
"description": "Root of a combobox: a text input that filters a list of options and writes the\nchosen one back into itself. The list opens on focus, on the first keystroke\nor from the chevron of `Input`'s `select` variant.\n\nFor a search against an API, set `minInputLength` so the list stays shut until\nthe query is worth sending: a field that opens an empty list on focus reads as\nbroken. For a pick from a short fixed list with no typing at all, prefer a\nselect.\n\nPass the options as `items`. For a list that comes from the server, set\n`filter={null}`, hand the already-filtered rows to `filteredItems`, and request\nthem from `onInputValueChange`; `Status` then announces the wait.\n\nEvery Base UI root prop is accepted and forwarded — `items`, `filter`,\n`value`, `onValueChange` and so on. `open` stays the consumer's to control;\n`minInputLength` only refuses to open below the minimum.\n\nWith `multiple`, the value is an array and picking a row toggles it. The list\nstays open and keeps the typed query between picks, so several rows can be\nticked from one search; closing the list (Escape, a click outside) still resets\nthe query. Each row then shows whether it is selected — see `Item`. Nothing is\nwritten back into the input: render the selection next to the field.",
|
|
2011
2011
|
"jsDocTags": {
|
|
2012
2012
|
"summary": [
|
|
2013
2013
|
"Root provider for an input-triggered filterable list"
|
|
@@ -2769,6 +2769,27 @@
|
|
|
2769
2769
|
"fileName": "node_modules/@base-ui/react/combobox/root/ComboboxRoot.d.mts"
|
|
2770
2770
|
}
|
|
2771
2771
|
]
|
|
2772
|
+
},
|
|
2773
|
+
"minInputLength": {
|
|
2774
|
+
"name": "minInputLength",
|
|
2775
|
+
"required": false,
|
|
2776
|
+
"type": {
|
|
2777
|
+
"name": "number"
|
|
2778
|
+
},
|
|
2779
|
+
"description": "Characters the query needs, spaces aside, before the list opens. Below it\nfocusing, clicking or pressing the chevron leaves the list shut, and\ndeleting back under it closes the list. Defaults to `0`: the list opens on\nfocus.",
|
|
2780
|
+
"defaultValue": {
|
|
2781
|
+
"value": "0"
|
|
2782
|
+
},
|
|
2783
|
+
"parent": {
|
|
2784
|
+
"name": "ComboboxRootProps",
|
|
2785
|
+
"fileName": "src/combobox/combobox.tsx"
|
|
2786
|
+
},
|
|
2787
|
+
"declarations": [
|
|
2788
|
+
{
|
|
2789
|
+
"name": "TypeLiteral",
|
|
2790
|
+
"fileName": "src/combobox/combobox.tsx"
|
|
2791
|
+
}
|
|
2792
|
+
]
|
|
2772
2793
|
}
|
|
2773
2794
|
}
|
|
2774
2795
|
},
|
|
@@ -2777,7 +2798,29 @@
|
|
|
2777
2798
|
"id": "components-combobox--default",
|
|
2778
2799
|
"name": "Default",
|
|
2779
2800
|
"snippet": "const Default = () => (\n <Combobox.Root items={STATES}>\n <Combobox.Input placeholder=\"Search states\" aria-label=\"Search states\" />\n <Combobox.Content>\n <Combobox.Empty>No matches found</Combobox.Empty>\n <Combobox.List>\n {(state: string) => (\n <Combobox.Item key={state} value={state}>\n {state}\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Content>\n </Combobox.Root>\n);",
|
|
2780
|
-
"description": "The common case: options are already in memory and Base UI filters them against\nwhat you type. Selecting a row fills the input and closes the list."
|
|
2801
|
+
"description": "The common case: options are already in memory and Base UI filters them against\nwhat you type. Selecting a row fills the input and closes the list. The field is\na search out of the box — a magnifier in front, a clear button once something is\npicked — and the list hangs from the whole field.",
|
|
2802
|
+
"summary": "Search field with a magnifier and clear button over an in-memory list"
|
|
2803
|
+
},
|
|
2804
|
+
{
|
|
2805
|
+
"id": "components-combobox--plain",
|
|
2806
|
+
"name": "Plain",
|
|
2807
|
+
"snippet": "const Plain = () => (\n <Combobox.Root items={STATES}>\n <Combobox.Input variant=\"plain\" placeholder=\"State\" aria-label=\"State\" />\n <Combobox.Content>\n <Combobox.Empty>No matches found</Combobox.Empty>\n <Combobox.List>\n {(state: string) => (\n <Combobox.Item key={state} value={state}>\n {state}\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Content>\n </Combobox.Root>\n);",
|
|
2808
|
+
"description": "`variant=\"plain\"`: the input alone, with no magnifier and no clear button, for a\nfield that needs no affordance — a FEIN lookup, a template name. The list still\nmatches the field's width.",
|
|
2809
|
+
"summary": "Bare input with no icon and no clear button"
|
|
2810
|
+
},
|
|
2811
|
+
{
|
|
2812
|
+
"id": "components-combobox--select",
|
|
2813
|
+
"name": "Select",
|
|
2814
|
+
"snippet": "const Select = () => (\n <Combobox.Root items={STATES}>\n <Combobox.Input variant=\"select\" placeholder=\"Choose a state\" aria-label=\"State\" />\n <Combobox.Content>\n <Combobox.Empty>No matches found</Combobox.Empty>\n <Combobox.List>\n {(state: string) => (\n <Combobox.Item key={state} value={state}>\n {state}\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Content>\n </Combobox.Root>\n);",
|
|
2815
|
+
"description": "`variant=\"select\"`: a chevron after the input opens and closes the list, for a\nshort known list the user may want to browse before typing. It has no clear\nbutton by default. The chevron is out of the tab order — the input already\nopens the list from the keyboard with the arrow keys.",
|
|
2816
|
+
"summary": "Field with a chevron that toggles the list, for short known lists"
|
|
2817
|
+
},
|
|
2818
|
+
{
|
|
2819
|
+
"id": "components-combobox--select-with-clear",
|
|
2820
|
+
"name": "Select With Clear",
|
|
2821
|
+
"snippet": "const SelectWithClear = () => (\n <Combobox.Root items={STATES} defaultValue=\"Florida\">\n <Combobox.Input variant=\"select\" showClear placeholder=\"Choose a state\" aria-label=\"State\" />\n <Combobox.Content>\n <Combobox.Empty>No matches found</Combobox.Empty>\n <Combobox.List>\n {(state: string) => (\n <Combobox.Item key={state} value={state}>\n {state}\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Content>\n </Combobox.Root>\n);",
|
|
2822
|
+
"description": "`showClear` overrides the variant's default: here it adds the clear button to a\n`select`, so a picked option can be removed without selecting the text and\ndeleting it. While there is a value it takes the chevron's place; clearing\nbrings the chevron back. Passing `false` drops it from `search`.",
|
|
2823
|
+
"summary": "Select field with a clear button added through showClear"
|
|
2781
2824
|
},
|
|
2782
2825
|
{
|
|
2783
2826
|
"id": "components-combobox--no-matches",
|
|
@@ -2800,8 +2843,9 @@
|
|
|
2800
2843
|
{
|
|
2801
2844
|
"id": "components-combobox--async-search-with-status",
|
|
2802
2845
|
"name": "Async Search With Status",
|
|
2803
|
-
"snippet": "const AsyncSearchWithStatus = () => {\n const [results, setResults] = useState<Agency[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n // Only the latest request may land; fast typing returns responses out of order.\n const latestRequest = useRef(0);\n\n const onInputValueChange = async (query: string) => {\n const request = ++latestRequest.current;\n\n // The previous rows go before the wait starts: a list that no longer matches what is typed\n // must not sit under the loading state.\n setResults([]);\n setIsLoading(true);\n const agencies = await searchAgencies(query);\n if (request !== latestRequest.current) return;\n\n setResults(agencies);\n setIsLoading(false);\n };\n\n return (\n // `filter={null}` hands filtering to the server; `filteredItems` is what came back.\n <Combobox.Root\n items={results}\n filteredItems={results}\n filter={null}\n itemToStringLabel={(agency: Agency) => agency.name}\n isItemEqualToValue={(a: Agency, b: Agency) => a.id === b.id}\n onInputValueChange={onInputValueChange}>\n <Combobox.Input placeholder=\"Search agencies\" aria-label=\"Search agencies\" />\n <Combobox.Content aria-busy={isLoading || undefined}>\n {/* The rows show the wait; `Status` only announces it. */}\n <Combobox.Status className=\"sr-only\">\n {isLoading ? 'Searching…' : undefined}\n </Combobox.Status>\n {isLoading && <SkeletonRows />}\n <Combobox.Empty>{isLoading ? undefined : 'No agencies found'}</Combobox.Empty>\n <Combobox.List>\n {(agency: Agency) => (\n <Combobox.Item key={agency.id} value={agency}>\n {agency.name}\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Content>\n </Combobox.Root>\n );\n};",
|
|
2804
|
-
"description": "The same search without Suspense, for a consumer that gets a `loading` flag from\nits data layer instead: `filter={null}`, the rows arrive through `filteredItems`,\n`Content` is marked busy and `Status` announces the wait. The list is cleared\nbefore each request and a request that is no longer the latest is dropped."
|
|
2846
|
+
"snippet": "const AsyncSearchWithStatus = () => {\n const [results, setResults] = useState<Agency[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n // Only the latest request may land; fast typing returns responses out of order.\n const latestRequest = useRef(0);\n\n const onInputValueChange = async (query: string) => {\n const request = ++latestRequest.current;\n if (query.trim().length < MIN_QUERY_LENGTH) {\n setResults([]);\n setIsLoading(false);\n return;\n }\n\n // The previous rows go before the wait starts: a list that no longer matches what is typed\n // must not sit under the loading state.\n setResults([]);\n setIsLoading(true);\n const agencies = await searchAgencies(query);\n if (request !== latestRequest.current) return;\n\n setResults(agencies);\n setIsLoading(false);\n };\n\n return (\n // `filter={null}` hands filtering to the server; `filteredItems` is what came back.\n <Combobox.Root\n items={results}\n filteredItems={results}\n filter={null}\n minInputLength={MIN_QUERY_LENGTH}\n itemToStringLabel={(agency: Agency) => agency.name}\n isItemEqualToValue={(a: Agency, b: Agency) => a.id === b.id}\n onInputValueChange={onInputValueChange}>\n <Combobox.Input placeholder=\"Search agencies\" aria-label=\"Search agencies\" />\n <Combobox.Content aria-busy={isLoading || undefined}>\n {/* The rows show the wait; `Status` only announces it. */}\n <Combobox.Status className=\"sr-only\">\n {isLoading ? 'Searching…' : undefined}\n </Combobox.Status>\n {isLoading && <SkeletonRows />}\n <Combobox.Empty>{isLoading ? undefined : 'No agencies found'}</Combobox.Empty>\n <Combobox.List>\n {(agency: Agency) => (\n <Combobox.Item key={agency.id} value={agency}>\n {agency.name}\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Content>\n </Combobox.Root>\n );\n};",
|
|
2847
|
+
"description": "The same search without Suspense, for a consumer that gets a `loading` flag from\nits data layer instead: `filter={null}`, the rows arrive through `filteredItems`,\n`Content` is marked busy and `Status` announces the wait. The list is cleared\nbefore each request and a request that is no longer the latest is dropped.\n\n`minInputLength` keeps the list shut until two characters are typed — focusing\nthe field opens nothing, and deleting back under the minimum closes it — and\nno request goes out for a shorter query either.",
|
|
2848
|
+
"summary": "API search that waits for two characters, with loading status"
|
|
2805
2849
|
},
|
|
2806
2850
|
{
|
|
2807
2851
|
"id": "components-combobox--inside-field-text",
|
|
@@ -2809,12 +2853,6 @@
|
|
|
2809
2853
|
"snippet": "const InsideFieldText = () => (\n <FieldText invalid required>\n <Label>Agency</Label>\n <Combobox.Root items={STATES}>\n <Combobox.Input placeholder=\"Search agencies\" />\n <Combobox.Content>\n <Combobox.Empty>No matches found</Combobox.Empty>\n <Combobox.List>\n {(state: string) => (\n <Combobox.Item key={state} value={state}>\n {state}\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Content>\n </Combobox.Root>\n <Field.Description>The agency this agent will be added to.</Field.Description>\n <Field.Error errors={[{ message: 'Pick an agency from the list' }]} />\n </FieldText>\n);",
|
|
2810
2854
|
"description": "Dropped into a `FieldText`, the input takes the label, the description and\nthe error from the field with nothing wired by hand: `Combobox.Input` reads the\nsame `InputContext` the plain `Input` does. It also points `aria-labelledby`\nat the label, so the name survives the list opening: Base UI then hides the\nrest of the page from assistive technology, label included, and a\n`<label for>` alone would stop naming the input."
|
|
2811
2855
|
},
|
|
2812
|
-
{
|
|
2813
|
-
"id": "components-combobox--with-leading-icon",
|
|
2814
|
-
"name": "With Leading Icon",
|
|
2815
|
-
"snippet": "const WithLeadingIcon = () => (\n <Combobox.Root items={STATES}>\n <div className=\"relative\">\n <IconSearch\n aria-hidden\n className=\"pointer-events-none absolute top-1/2 left-3 -z-hide size-6 -translate-y-1/2 [&>path]:fill-icon-default-base-tertiary\"\n />\n <Combobox.Input className=\"pl-11\" placeholder=\"Search states\" aria-label=\"Search states\" />\n </div>\n <Combobox.Content>\n <Combobox.Empty>No matches found</Combobox.Empty>\n <Combobox.List>\n {(state: string) => (\n <Combobox.Item key={state} value={state}>\n {state}\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Content>\n </Combobox.Root>\n);",
|
|
2816
|
-
"description": "A leading icon is composed around the input, not baked in: not every combobox\nis a search (a FEIN lookup or a template picker are not), so the component\nships no icon of its own. Until `InputGroup` lands in the design system, the\nmarketplace search fields get theirs like this — the icon overlaid, the input\npadded past it."
|
|
2817
|
-
},
|
|
2818
2856
|
{
|
|
2819
2857
|
"id": "components-combobox--inside-modal",
|
|
2820
2858
|
"name": "Inside Modal",
|
|
@@ -2822,7 +2860,7 @@
|
|
|
2822
2860
|
"description": "Inside a `Modal`, which is a Radix Dialog. The surface portals to the body, so\nthis checks that the dialog's modal layer neither blocks pointer events on the\nlist nor treats a click in it as a click outside and closes."
|
|
2823
2861
|
}
|
|
2824
2862
|
],
|
|
2825
|
-
"import": "import {
|
|
2863
|
+
"import": "import { Button, Combobox, Field, FieldText, Label, Modal, Skeleton, Tag } from \"@agentero/design-system\";\nimport { Suspense } from \"react\";"
|
|
2826
2864
|
},
|
|
2827
2865
|
"components-command": {
|
|
2828
2866
|
"id": "components-command",
|
|
@@ -9552,6 +9590,6 @@
|
|
|
9552
9590
|
},
|
|
9553
9591
|
"meta": {
|
|
9554
9592
|
"docgen": "react-component-meta",
|
|
9555
|
-
"durationMs":
|
|
9593
|
+
"durationMs": 4877
|
|
9556
9594
|
}
|
|
9557
9595
|
}
|
package/package.json
CHANGED
|
@@ -35,7 +35,7 @@ var d = ({ className: r, children: s, asChild: c, ...l }) => /* @__PURE__ */ a(u
|
|
|
35
35
|
d.displayName = "Accordion.Trigger";
|
|
36
36
|
var f = ({ className: t, children: r, ...i }) => /* @__PURE__ */ a(n.Content, {
|
|
37
37
|
"data-slot": "accordion-content",
|
|
38
|
-
className: e("overflow-hidden px-4 text-sm", "motion-safe:data-[state=open]:animate-
|
|
38
|
+
className: e("overflow-hidden px-4 text-sm", "motion-safe:data-[state=open]:animate-accordion-down", "motion-safe:data-[state=closed]:animate-accordion-up", t),
|
|
39
39
|
...i,
|
|
40
40
|
children: /* @__PURE__ */ a("div", {
|
|
41
41
|
className: "pb-4",
|
package/src/avatar/avatar.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn as e } from "../../lib/utils.js";
|
|
3
3
|
import { tv as t } from "tailwind-variants";
|
|
4
|
-
import { createContext as n, use as r } from "react";
|
|
5
|
-
import { jsx as
|
|
6
|
-
import * as
|
|
4
|
+
import { createContext as n, use as r, useState as i } from "react";
|
|
5
|
+
import { jsx as a, jsxs as o } from "react/jsx-runtime";
|
|
6
|
+
import * as s from "@radix-ui/react-avatar";
|
|
7
7
|
//#region src/avatar/avatar.tsx
|
|
8
|
-
var
|
|
8
|
+
var c = t({
|
|
9
9
|
slots: {
|
|
10
10
|
root: [
|
|
11
11
|
"flex items-center justify-center align-middle",
|
|
@@ -17,7 +17,7 @@ var s = t({
|
|
|
17
17
|
"border-[var(--avatar-border-color,var(--color-border-default-base-primary))]",
|
|
18
18
|
"h-fit w-fit"
|
|
19
19
|
],
|
|
20
|
-
image: ["flex object-cover box-border h-full vertical-align-middle w-full"],
|
|
20
|
+
image: ["flex object-cover box-border h-full vertical-align-middle w-full", "data-loaded-late:transition-opacity data-loaded-late:duration-200 data-loaded-late:starting:opacity-0"],
|
|
21
21
|
fallback: ["uppercase", "[&_svg]:size-[1.5em] [&_svg]:fill-neutral-500"]
|
|
22
22
|
},
|
|
23
23
|
variants: {
|
|
@@ -126,58 +126,63 @@ var s = t({
|
|
|
126
126
|
variant: "circle",
|
|
127
127
|
type: "photo"
|
|
128
128
|
}
|
|
129
|
-
}),
|
|
130
|
-
let e = r(
|
|
129
|
+
}), l = n(null), u = () => {
|
|
130
|
+
let e = r(l);
|
|
131
131
|
if (!e) throw Error("useAvatar must be used within an AvatarProvider");
|
|
132
132
|
return e;
|
|
133
|
-
},
|
|
134
|
-
let
|
|
133
|
+
}, d = ({ size: t, variant: n, type: r, ...i }) => {
|
|
134
|
+
let o = c({
|
|
135
135
|
size: t,
|
|
136
136
|
variant: n,
|
|
137
137
|
type: r
|
|
138
138
|
});
|
|
139
|
-
return /* @__PURE__ */
|
|
139
|
+
return /* @__PURE__ */ a(l, {
|
|
140
140
|
value: {
|
|
141
141
|
size: t,
|
|
142
142
|
variant: n,
|
|
143
143
|
type: r,
|
|
144
|
-
slotsStyles:
|
|
144
|
+
slotsStyles: o
|
|
145
145
|
},
|
|
146
|
-
children: /* @__PURE__ */
|
|
147
|
-
...
|
|
148
|
-
className: e(
|
|
146
|
+
children: /* @__PURE__ */ a(s.Root, {
|
|
147
|
+
...i,
|
|
148
|
+
className: e(o.root(), i.className)
|
|
149
149
|
})
|
|
150
150
|
});
|
|
151
|
-
},
|
|
152
|
-
let { slotsStyles:
|
|
153
|
-
return /* @__PURE__ */
|
|
154
|
-
...
|
|
155
|
-
|
|
151
|
+
}, f = ({ onLoadingStatusChange: t, ...n }) => {
|
|
152
|
+
let { slotsStyles: r } = u(), [o, c] = i(!1);
|
|
153
|
+
return /* @__PURE__ */ a(s.Image, {
|
|
154
|
+
...n,
|
|
155
|
+
"data-loaded-late": o || void 0,
|
|
156
|
+
onLoadingStatusChange: (e) => {
|
|
157
|
+
e === "loading" && c(!0), t?.(e);
|
|
158
|
+
},
|
|
159
|
+
className: e(r.image(), n.className)
|
|
156
160
|
});
|
|
157
|
-
},
|
|
158
|
-
let { slotsStyles: n } =
|
|
159
|
-
return /* @__PURE__ */
|
|
161
|
+
}, p = (t) => {
|
|
162
|
+
let { slotsStyles: n } = u();
|
|
163
|
+
return /* @__PURE__ */ a(s.Fallback, {
|
|
160
164
|
...t,
|
|
161
165
|
className: e(n.fallback(), t.className)
|
|
162
166
|
});
|
|
163
|
-
},
|
|
164
|
-
let
|
|
165
|
-
return /* @__PURE__ */
|
|
166
|
-
...
|
|
167
|
-
ref:
|
|
168
|
-
size:
|
|
169
|
-
variant:
|
|
170
|
-
type:
|
|
167
|
+
}, m = ({ alt: e, src: t, fallback: n, colorize: r, size: s, variant: c, type: l, ref: u, ...m }) => {
|
|
168
|
+
let h = r ? _(r) : void 0, [g, v] = i(!1);
|
|
169
|
+
return /* @__PURE__ */ o(d, {
|
|
170
|
+
...m,
|
|
171
|
+
ref: u,
|
|
172
|
+
size: s,
|
|
173
|
+
variant: c,
|
|
174
|
+
type: l,
|
|
171
175
|
style: {
|
|
172
|
-
...
|
|
173
|
-
...
|
|
176
|
+
...h,
|
|
177
|
+
...m.style
|
|
174
178
|
},
|
|
175
|
-
children: [/* @__PURE__ */
|
|
179
|
+
children: [/* @__PURE__ */ a(f, {
|
|
176
180
|
alt: e,
|
|
177
|
-
src: t
|
|
178
|
-
|
|
181
|
+
src: t,
|
|
182
|
+
onLoadingStatusChange: (e) => v(e === "error")
|
|
183
|
+
}), (!t || g) && /* @__PURE__ */ a(p, { children: n })]
|
|
179
184
|
});
|
|
180
|
-
},
|
|
185
|
+
}, h = [
|
|
181
186
|
{
|
|
182
187
|
dark: "#434343",
|
|
183
188
|
light: "#e3e3e3"
|
|
@@ -214,15 +219,15 @@ var s = t({
|
|
|
214
219
|
dark: "#0f8a2a",
|
|
215
220
|
light: "#d1fada"
|
|
216
221
|
}
|
|
217
|
-
],
|
|
222
|
+
], g = (e) => {
|
|
218
223
|
let t = e.split("").reduce((e, t, n) => {
|
|
219
224
|
let r = 1;
|
|
220
225
|
for (let e = 0; e < n; e++) r *= 26;
|
|
221
226
|
return e + (t.charCodeAt(0) - 97 + 1) * r;
|
|
222
227
|
}, 0);
|
|
223
|
-
return
|
|
224
|
-
},
|
|
225
|
-
let { dark: t, light: n } =
|
|
228
|
+
return h[(t < 0 ? -t : t) % h.length];
|
|
229
|
+
}, _ = (e) => {
|
|
230
|
+
let { dark: t, light: n } = g(e);
|
|
226
231
|
return {
|
|
227
232
|
color: t,
|
|
228
233
|
backgroundColor: n,
|
|
@@ -230,4 +235,4 @@ var s = t({
|
|
|
230
235
|
};
|
|
231
236
|
};
|
|
232
237
|
//#endregion
|
|
233
|
-
export {
|
|
238
|
+
export { m as Avatar, c as avatarRecipe, u as useAvatar };
|
package/src/button/button.js
CHANGED
|
@@ -245,7 +245,7 @@ var c = t({
|
|
|
245
245
|
}), l = () => /* @__PURE__ */ i("span", {
|
|
246
246
|
"aria-label": "loading",
|
|
247
247
|
role: "status",
|
|
248
|
-
className: e("absolute inset-0 grid place-items-center", "rounded-[inherit] bg-inherit", "before:content-[\"\"] before:block before:size-[1em]", "before:border-2 before:border-solid before:rounded-full", "before:border-current before:border-t-transparent", "before:animate-spin before:[animation-duration:0.5s]")
|
|
248
|
+
className: e("absolute inset-0 grid place-items-center", "rounded-[inherit] bg-inherit", "transition-opacity duration-150 starting:opacity-0", "before:content-[\"\"] before:block before:size-[1em]", "before:border-2 before:border-solid before:rounded-full", "before:border-current before:border-t-transparent", "before:animate-spin before:[animation-duration:0.5s]")
|
|
249
249
|
}), u = ({ children: t, asChild: u, variant: d, size: f, status: p, loading: m, rounded: h, align: g, fitContent: _, disabled: v, iconOnly: y, ref: b, className: x, ...S }) => {
|
|
250
250
|
let C = u ? !!y : n.toArray(t).every((e) => r(e)), w = v || m;
|
|
251
251
|
process.env.NODE_ENV !== "production" && (m && d === "link" && console.warn("Button with variant link and loading is not supported"), C && d === "link" && console.warn("Button with no text and variant link is not supported. Use it with variant tertiary instead"), u && y && r(t) && n.toArray(t.props.children).some((e) => !r(e)) && console.warn("Button with asChild and iconOnly should only contain icon children; text found inside the wrapper element"));
|
package/src/checkbox/checkbox.js
CHANGED
|
@@ -8,7 +8,7 @@ var s = r({ slots: {
|
|
|
8
8
|
root: [
|
|
9
9
|
"group/checkbox box-border inline-flex size-4 shrink-0 appearance-none items-center justify-center rounded-sm",
|
|
10
10
|
"border border-solid border-border-input-default bg-bg-input-normal",
|
|
11
|
-
"cursor-pointer transition-colors duration-
|
|
11
|
+
"cursor-pointer transition-colors duration-150",
|
|
12
12
|
"data-[state=checked]:border-bg-checkbox-selected data-[state=checked]:bg-bg-checkbox-selected",
|
|
13
13
|
"data-[state=indeterminate]:border-bg-checkbox-selected data-[state=indeterminate]:bg-bg-checkbox-selected",
|
|
14
14
|
"outline-solid outline-2 outline-offset-2 outline-transparent",
|