torch-glare 2.1.2 → 2.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/apps/lib/components/Avatar.tsx +1 -1
  2. package/apps/lib/components/Card.tsx +68 -54
  3. package/apps/lib/components/DataViews/DataViewRadio.tsx +47 -0
  4. package/apps/lib/components/DataViews/DataViewsConfigPanel.tsx +56 -45
  5. package/apps/lib/components/DataViews/DataViewsHeader.tsx +130 -28
  6. package/apps/lib/components/DataViews/DataViewsLayout.tsx +32 -2
  7. package/apps/lib/components/DataViews/FilterPanel.tsx +148 -3
  8. package/apps/lib/components/DataViews/HeaderSearch.tsx +97 -0
  9. package/apps/lib/components/DataViews/InboxView.tsx +263 -282
  10. package/apps/lib/components/DataViews/InboxViewCard.tsx +136 -0
  11. package/apps/lib/components/DataViews/KanbanView.tsx +264 -153
  12. package/apps/lib/components/DataViews/PanelControls.tsx +10 -41
  13. package/apps/lib/components/DataViews/TreeView.tsx +220 -191
  14. package/apps/lib/components/DataViews/index.ts +6 -0
  15. package/apps/lib/components/DataViews/types.ts +30 -1
  16. package/apps/lib/components/Radio.tsx +18 -21
  17. package/apps/lib/components/Switch.tsx +3 -1
  18. package/apps/lib/components/Table.tsx +1 -1
  19. package/apps/lib/components/TreeFolder/TreeFolder.tsx +160 -137
  20. package/apps/lib/components/TreeFolder/TreeFolderRow.tsx +221 -93
  21. package/apps/lib/components/TreeFolder/types.ts +9 -0
  22. package/apps/lib/layouts/DataViewCard.tsx +76 -0
  23. package/dist/src/shared/copyComponentsRecursively.js +9 -1
  24. package/dist/src/shared/copyComponentsRecursively.js.map +1 -1
  25. package/dist/src/shared/getDependenciesAndInstallNestedComponents.d.ts.map +1 -1
  26. package/dist/src/shared/getDependenciesAndInstallNestedComponents.js +9 -1
  27. package/dist/src/shared/getDependenciesAndInstallNestedComponents.js.map +1 -1
  28. package/docs/components/data-views-config-panel.md +204 -0
  29. package/docs/components/data-views-layout.md +270 -0
  30. package/package.json +1 -1
@@ -38,7 +38,7 @@ const AvatarFallback = React.forwardRef<
38
38
  <AvatarPrimitive.Fallback
39
39
  ref={ref}
40
40
  className={cn(
41
- "flex h-full w-full items-center justify-center rounded-full bg-background-system-body-tertiary text-content-presentation-global-primary",
41
+ "flex h-full w-full items-center justify-center rounded-full bg-background-presentation-action-disabled text-content-presentation-global-primary",
42
42
  className
43
43
  )}
44
44
  {...props}
@@ -1,64 +1,78 @@
1
- import { cn } from '../utils/cn';
2
- import React, { HTMLAttributes } from 'react'
1
+ import { cn } from "../utils/cn";
2
+ import React, { HTMLAttributes } from "react";
3
3
  import { Slot } from "@radix-ui/react-slot";
4
4
 
5
-
6
- interface Props extends Omit<HTMLAttributes<HTMLDivElement | HTMLHeadingElement | HTMLParagraphElement | HTMLLabelElement>, 'htmlFor'> {
7
- as?: React.ElementType;
8
- asChild?: boolean;
9
- htmlFor?: string;
10
- }
11
- export const Card = ({ className, htmlFor, asChild, as: Tag = "section", ...props }: Props) => {
12
- const Component = asChild ? Slot : Tag;
13
- return (
14
- <Component htmlFor={htmlFor} {...props} className={cn(
15
- "flex flex-col justify-start",
16
- "gap-2 rounded-[12px] border",
17
- "transition-all ease-in-out duration-200",
18
- "p-[16px]",
19
- "border-border-presentation-global-primary",
20
- "bg-background-presentation-form-radiocard-base",
21
- "hover:border-border-presentation-state-focus",
22
- "focus:border-border-presentation-state-focus",
23
- className
24
- )} />
25
- )
5
+ interface Props extends Omit<
6
+ HTMLAttributes<
7
+ | HTMLDivElement
8
+ | HTMLHeadingElement
9
+ | HTMLParagraphElement
10
+ | HTMLLabelElement
11
+ >,
12
+ "htmlFor"
13
+ > {
14
+ as?: React.ElementType;
15
+ asChild?: boolean;
16
+ htmlFor?: string;
26
17
  }
18
+ export const Card = ({
19
+ className,
20
+ htmlFor,
21
+ asChild,
22
+ as: Tag = "section",
23
+ ...props
24
+ }: Props) => {
25
+ const Component = asChild ? Slot : Tag;
26
+ return (
27
+ <Component
28
+ htmlFor={htmlFor}
29
+ {...props}
30
+ className={cn(
31
+ "flex flex-col justify-start",
32
+ "gap-2 rounded-[12px] border",
33
+ "transition-all ease-in-out duration-200",
34
+ "p-[16px]",
35
+ "border-border-presentation-global-primary",
36
+ "bg-background-presentation-form-radiocard-base",
37
+ "hover:border-border-presentation-state-focus",
38
+ "focus:border-border-presentation-state-focus",
39
+ className,
40
+ )}
41
+ />
42
+ );
43
+ };
27
44
 
28
-
29
-
30
- interface GeneralProps extends HTMLAttributes<HTMLHeadingElement> { }
45
+ interface GeneralProps extends HTMLAttributes<HTMLHeadingElement> {}
31
46
 
32
47
  export const CardHeader = ({ className, ...props }: GeneralProps) => {
33
- return (
34
- <div
35
- {...props}
36
- className={cn(
37
- "text-content-presentation-global-primary m-0 typography-headers-medium-semibold",
38
- className
39
- )}
40
- >
41
- </div>
42
- )
43
- }
48
+ return (
49
+ <div
50
+ {...props}
51
+ className={cn(
52
+ "text-content-presentation-global-primary m-0 typography-headers-medium-semibold",
53
+ className,
54
+ )}
55
+ ></div>
56
+ );
57
+ };
44
58
 
45
59
  export const CardDescription = ({ className, ...props }: GeneralProps) => {
46
- return (
47
- <div
48
- {...props}
49
- className={cn(
50
- "text-content-presentation-global-primary m-0 typography-body-medium-semibold",
51
- className
52
- )}
53
- >
54
- </div>
55
- )
56
- }
60
+ return (
61
+ <div
62
+ {...props}
63
+ className={cn(
64
+ "text-content-presentation-global-primary m-0 typography-body-medium-semibold",
65
+ className,
66
+ )}
67
+ ></div>
68
+ );
69
+ };
57
70
 
58
71
  export const CardContent = ({ className, ...props }: GeneralProps) => {
59
- return (
60
- <section {...props} className={cn("flex gap-1 flex-col items-start flex-1", className)}>
61
- </section>
62
- )
63
- }
64
-
72
+ return (
73
+ <section
74
+ {...props}
75
+ className={cn("flex gap-1 flex-col items-start flex-1", className)}
76
+ ></section>
77
+ );
78
+ };
@@ -0,0 +1,47 @@
1
+ "use client";
2
+
3
+ import { type ReactNode } from "react";
4
+ import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
5
+ import { cn } from "../../utils/cn";
6
+
7
+ export interface DataViewRadioProps {
8
+ value: string;
9
+ label?: string;
10
+ children?: ReactNode;
11
+ className?: string;
12
+ }
13
+
14
+ export function DataViewRadio({
15
+ value,
16
+ label,
17
+ children,
18
+ className,
19
+ }: DataViewRadioProps) {
20
+ return (
21
+ <RadioGroupPrimitive.Item
22
+ value={value}
23
+ className={cn(
24
+ "group flex w-full items-center gap-1.5 py-1 ps-2 h-[32px]",
25
+ "cursor-pointer rounded-[8px] text-left outline-none transition-colors",
26
+ "hover:bg-background-presentation-action-contstyle-hover focus-visible:bg-background-presentation-action-contstyle-hover",
27
+ className,
28
+ )}
29
+ >
30
+ <span
31
+ className={cn(
32
+ "flex h-[14px] w-[14px] shrink-0 items-center justify-center rounded-full",
33
+ "border border-border-presentation-action-primary bg-background-presentation-form-field-primary transition-colors",
34
+ "group-data-[state=checked]:border-transparent",
35
+ "group-data-[state=checked]:bg-border-presentation-state-focus",
36
+ )}
37
+ >
38
+ <RadioGroupPrimitive.Indicator className="flex items-center justify-center">
39
+ <span className="h-[6px] w-[6px] rounded-full bg-white" />
40
+ </RadioGroupPrimitive.Indicator>
41
+ </span>
42
+ <span className="flex-1 typography-body-medium-regular text-content-presentation-global-primary">
43
+ {children ?? label}
44
+ </span>
45
+ </RadioGroupPrimitive.Item>
46
+ );
47
+ }
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { useMemo, useState } from "react";
3
+ import { Fragment, useMemo, useState } from "react";
4
4
  import {
5
5
  X,
6
6
  Settings as SettingsIcon,
@@ -163,25 +163,21 @@ export function DataViewsConfigPanel(props: DataViewsConfigPanelProps) {
163
163
  };
164
164
 
165
165
  const [dragPath, setDragPath] = useState<string | null>(null);
166
- const [dragOverPath, setDragOverPath] = useState<string | null>(null);
167
- // Whether the drop will land before (true) or after (false) dragOverPath.
168
- const [dropBefore, setDropBefore] = useState(true);
166
+ // Insertion slot in the ordered list: 0 means before the first row, N means
167
+ // after the last row (count). Single source of truth — there is exactly one
168
+ // indicator at a time, so no double-line ambiguity between adjacent rows.
169
+ const [dropSlot, setDropSlot] = useState<number | null>(null);
169
170
 
170
- const reorderColumn = (
171
- sourcePath: string,
172
- targetPath: string,
173
- before: boolean,
174
- ) => {
175
- if (sourcePath === targetPath) return;
171
+ const reorderColumnToSlot = (sourcePath: string, slot: number) => {
176
172
  const ids = orderedColumns.map((c) => c.id);
177
173
  const from = ids.indexOf(sourcePath);
178
- let to = ids.indexOf(targetPath);
179
- if (from === -1 || to === -1) return;
174
+ if (from === -1) return;
175
+ // Dropping into the same logical position (before or after itself) is a no-op.
176
+ if (slot === from || slot === from + 1) return;
180
177
  const reordered = [...ids];
181
178
  reordered.splice(from, 1);
182
- // Recompute the target index after removal, then offset for before/after.
183
- to = reordered.indexOf(targetPath);
184
- const insertAt = before ? to : to + 1;
179
+ // After removal, indices shift left by 1 for any slot beyond `from`.
180
+ const insertAt = slot > from ? slot - 1 : slot;
185
181
  reordered.splice(insertAt, 0, sourcePath);
186
182
  const orderByPath = new Map(reordered.map((id, i) => [id, i]));
187
183
  const next = config.tableColumns.map((c) => {
@@ -290,14 +286,17 @@ export function DataViewsConfigPanel(props: DataViewsConfigPanelProps) {
290
286
  </p>
291
287
  ) : (
292
288
  <div data-theme="dark" className="flex flex-col gap-2">
293
- {orderedColumns.map((col) => {
289
+ {orderedColumns.map((col, index) => {
294
290
  const field = fieldByPath.get(col.id);
295
291
  const isDragging = dragPath === col.id;
296
- const isTarget =
297
- dragOverPath === col.id && dragPath !== col.id;
292
+ // Slot for the cursor on this row: top half = insert at
293
+ // `index` (before this row); bottom half = `index + 1`
294
+ // (after this row, which is the SAME slot as "before next
295
+ // row" — the single source of truth avoids the old
296
+ // double-line problem in the gap between rows).
298
297
  return (
299
298
  <div key={col.id}>
300
- {isTarget && dropBefore && <DropLine />}
299
+ {dropSlot === index && dragPath && <DropLine />}
301
300
  <div
302
301
  draggable
303
302
  onDragStart={(e) => {
@@ -312,29 +311,25 @@ export function DataViewsConfigPanel(props: DataViewsConfigPanelProps) {
312
311
  e.currentTarget.getBoundingClientRect();
313
312
  const before =
314
313
  e.clientY < rect.top + rect.height / 2;
315
- if (dragOverPath !== col.id)
316
- setDragOverPath(col.id);
317
- if (dropBefore !== before) setDropBefore(before);
318
- }}
319
- onDragLeave={() => {
320
- if (dragOverPath === col.id) setDragOverPath(null);
314
+ const slot = before ? index : index + 1;
315
+ if (dropSlot !== slot) setDropSlot(slot);
321
316
  }}
322
317
  onDrop={(e) => {
323
318
  e.preventDefault();
324
- if (dragPath)
325
- reorderColumn(dragPath, col.id, dropBefore);
319
+ if (dragPath && dropSlot != null)
320
+ reorderColumnToSlot(dragPath, dropSlot);
326
321
  setDragPath(null);
327
- setDragOverPath(null);
322
+ setDropSlot(null);
328
323
  }}
329
324
  onDragEnd={() => {
330
325
  setDragPath(null);
331
- setDragOverPath(null);
326
+ setDropSlot(null);
332
327
  }}
333
328
  className={cn(
334
329
  // SB-Column-Item: standalone #1C1D1F pill, #252729
335
330
  // border. Figma container spec: 8px radius, 8.8px
336
331
  // padding, 8px gap between grip / label / switch.
337
- "flex items-center gap-2 rounded-r-[99px] rounded-l-[60px] border border-[#252729] bg-[#1C1D1F] p-[8.8px] transition-colors cursor-grab active:cursor-grabbing",
332
+ "flex items-center gap-2 rounded-e-[99px] rounded-s-[60px] border border-[#252729] bg-[#1C1D1F] p-[8.8px] transition-colors cursor-grab active:cursor-grabbing",
338
333
  isDragging ? "opacity-50" : "hover:bg-[#252729]",
339
334
  )}
340
335
  >
@@ -353,10 +348,14 @@ export function DataViewsConfigPanel(props: DataViewsConfigPanelProps) {
353
348
  />
354
349
  </span>
355
350
  </div>
356
- {isTarget && !dropBefore && <DropLine />}
357
351
  </div>
358
352
  );
359
353
  })}
354
+ {/* Drop-at-end indicator: only ever rendered when the slot
355
+ points past the last row, so still exactly one line. */}
356
+ {dropSlot === orderedColumns.length && dragPath && (
357
+ <DropLine />
358
+ )}
360
359
  </div>
361
360
  )}
362
361
  </div>
@@ -373,10 +372,21 @@ export function DataViewsConfigPanel(props: DataViewsConfigPanelProps) {
373
372
  ) : (
374
373
  // Single-choice radio list (Figma 1612:30016): selecting a
375
374
  // column sets config.sortBy; direction keeps config.sortOrder.
375
+ // Rows + dividers are flat siblings so the `peer` pattern
376
+ // can hide the dividers immediately before AND after a
377
+ // hovered row.
376
378
  <RadioGroup
377
379
  value={config.sortBy || undefined}
378
380
  onValueChange={(v) => onConfigChange({ sortBy: v })}
379
- className="flex flex-col gap-1 space-y-0 rounded-[12px] bg-[#1C1D1F] p-1"
381
+ className={cn(
382
+ "flex flex-col space-y-0 rounded-[12px] bg-[#1C1D1F] p-1",
383
+ // Wrapper containing the hovered row: hide its OWN
384
+ // divider (sits above the row).
385
+ "[&>div:has(>[role=radio]:hover)>.dv-divider]:opacity-0",
386
+ // Wrapper that directly follows the one with the hovered
387
+ // row: hide its divider (sits below the hovered row).
388
+ "[&>div:has(>[role=radio]:hover)+div>.dv-divider]:opacity-0",
389
+ )}
380
390
  >
381
391
  {sortableColumns.map((col, i) => {
382
392
  const field = fieldByPath.get(col.id);
@@ -384,7 +394,9 @@ export function DataViewsConfigPanel(props: DataViewsConfigPanelProps) {
384
394
  <div key={col.id}>
385
395
  {/* Edge-to-edge divider (Figma: no horizontal
386
396
  inset). */}
387
- {i > 0 && <div className="h-px bg-[#2C2D2E]" />}
397
+ {i > 0 && (
398
+ <div className="dv-divider h-px bg-[#2C2D2E]" />
399
+ )}
388
400
  <RadioRow
389
401
  value={col.id}
390
402
  label={col.label || field?.label || col.id}
@@ -397,18 +409,17 @@ export function DataViewsConfigPanel(props: DataViewsConfigPanelProps) {
397
409
  </div>
398
410
  </div>
399
411
  ) : (
400
- <div className="[&>div]:w-full [&>div]:border-r-0 [&>div]:bg-transparent">
401
- <FilterPanel
402
- data={data}
403
- fields={fields}
404
- filters={filterState}
405
- onFilterChange={(path: string, value: FilterValue) =>
406
- onFilterChange({ ...filterState, [path]: value })
407
- }
408
- onClearAll={() => onFilterChange({})}
409
- filterConfig={filterConfig}
410
- />
411
- </div>
412
+ <FilterPanel
413
+ variant="panel"
414
+ data={data}
415
+ fields={fields}
416
+ filters={filterState}
417
+ onFilterChange={(path: string, value: FilterValue) =>
418
+ onFilterChange({ ...filterState, [path]: value })
419
+ }
420
+ onClearAll={() => onFilterChange({})}
421
+ filterConfig={filterConfig}
422
+ />
412
423
  )}
413
424
  </div>
414
425
  </div>
@@ -1,29 +1,32 @@
1
- "use client"
1
+ "use client";
2
2
 
3
- import { Settings } from "lucide-react"
4
- import type { ReactNode } from "react"
5
- import type { ViewType } from "./types"
6
- import { Button } from "../Button"
7
- import { cn } from "../../utils/cn"
3
+ import { Search, Settings } from "lucide-react";
4
+ import { useEffect, useRef, useState, type ReactNode } from "react";
5
+ import type { ViewType } from "./types";
6
+ import { Button } from "../Button";
7
+ import { cn } from "../../utils/cn";
8
8
 
9
9
  export type DataViewsHeaderView = {
10
- id: ViewType
11
- label: string
12
- icon: ReactNode
13
- }
10
+ id: ViewType;
11
+ label: string;
12
+ icon: ReactNode;
13
+ };
14
14
 
15
15
  type DataViewsHeaderProps = {
16
- title: string
17
- views: DataViewsHeaderView[]
18
- currentView: ViewType
19
- onViewChange: (view: ViewType) => void
20
- showSettings: boolean
21
- settingsOpen: boolean
22
- onToggleSettings: () => void
23
- onAddNew?: () => void
24
- addNewLabel?: string
25
- className?: string
26
- }
16
+ title: string;
17
+ views: DataViewsHeaderView[];
18
+ currentView: ViewType;
19
+ onViewChange: (view: ViewType) => void;
20
+ showSettings: boolean;
21
+ settingsOpen: boolean;
22
+ onToggleSettings: () => void;
23
+ onAddNew?: () => void;
24
+ addNewLabel?: string;
25
+ searchValue?: string;
26
+ onSearchChange?: (value: string) => void;
27
+ searchPlaceholder?: string;
28
+ className?: string;
29
+ };
27
30
 
28
31
  export function DataViewsHeader({
29
32
  title,
@@ -35,6 +38,9 @@ export function DataViewsHeader({
35
38
  onToggleSettings,
36
39
  onAddNew,
37
40
  addNewLabel = "Add New",
41
+ searchValue,
42
+ onSearchChange,
43
+ searchPlaceholder = "Search...",
38
44
  className,
39
45
  }: DataViewsHeaderProps) {
40
46
  return (
@@ -56,17 +62,17 @@ export function DataViewsHeader({
56
62
  </div>
57
63
 
58
64
  {/* Divider */}
59
- <div className="h-7 w-px shrink-0 bg-[#434446]" />
65
+ <div className="h-5 w-px shrink-0 bg-[#434446]" />
60
66
 
61
67
  {/* Segmented view switcher */}
62
- <div className="flex flex-1 items-center">
68
+ <div className="flex flex-1 items-center gap-2">
63
69
  <div className="flex items-center gap-[2px] rounded-[10px] bg-[#252729] p-[2px] shadow-[inset_0_0_4px_0_rgba(0,0,0,0.08)]">
64
70
  {views.map((view, idx) => {
65
- const active = view.id === currentView
66
- const prevActive = idx > 0 && views[idx - 1].id === currentView
71
+ const active = view.id === currentView;
72
+ const prevActive = idx > 0 && views[idx - 1].id === currentView;
67
73
  // Separator sits between two inactive tabs only; the active white
68
74
  // pill never has a flanking divider (matches Figma).
69
- const showDivider = idx > 0 && !active && !prevActive
75
+ const showDivider = idx > 0 && !active && !prevActive;
70
76
  return (
71
77
  <div key={view.id} className="flex items-center">
72
78
  {showDivider && (
@@ -89,13 +95,20 @@ export function DataViewsHeader({
89
95
  {view.label}
90
96
  </button>
91
97
  </div>
92
- )
98
+ );
93
99
  })}
94
100
  </div>
95
101
  </div>
96
102
 
97
103
  {/* Action bar */}
98
104
  <div className="flex shrink-0 items-center gap-2">
105
+ {onSearchChange && (
106
+ <HeaderSearch
107
+ value={searchValue ?? ""}
108
+ onChange={onSearchChange}
109
+ placeholder={searchPlaceholder}
110
+ />
111
+ )}
99
112
  {onAddNew && (
100
113
  <Button
101
114
  variant="PrimeStyle"
@@ -122,5 +135,94 @@ export function DataViewsHeader({
122
135
  )}
123
136
  </div>
124
137
  </div>
125
- )
138
+ );
139
+ }
140
+
141
+ function HeaderSearch({
142
+ value,
143
+ onChange,
144
+ placeholder,
145
+ }: {
146
+ value: string;
147
+ onChange: (value: string) => void;
148
+ placeholder: string;
149
+ }) {
150
+ const [open, setOpen] = useState(false);
151
+ const inputRef = useRef<HTMLInputElement>(null);
152
+ const wrapRef = useRef<HTMLDivElement>(null);
153
+
154
+ useEffect(() => {
155
+ if (open) inputRef.current?.focus();
156
+ }, [open]);
157
+
158
+ // Auto-collapse on outside click only when the input is empty — keeps the
159
+ // expanded state if the user has typed a query but clicks away.
160
+ useEffect(() => {
161
+ if (!open) return;
162
+ function onPointerDown(e: MouseEvent) {
163
+ if (!wrapRef.current) return;
164
+ if (wrapRef.current.contains(e.target as Node)) return;
165
+ if (!value) setOpen(false);
166
+ }
167
+ document.addEventListener("mousedown", onPointerDown);
168
+ return () => document.removeEventListener("mousedown", onPointerDown);
169
+ }, [open, value]);
170
+
171
+ function clearAndCollapse() {
172
+ onChange("");
173
+ setOpen(false);
174
+ }
175
+
176
+ if (!open) {
177
+ return (
178
+ <Button
179
+ variant="BluContStyle"
180
+ size="M"
181
+ buttonType="icon"
182
+ aria-label="Open search"
183
+ onClick={() => setOpen(true)}
184
+ className="shrink-0 rounded-[6px] border border-border-presentation-global-primary"
185
+ >
186
+ <Search className="h-[18px] w-[18px]" />
187
+ </Button>
188
+ );
189
+ }
190
+
191
+ return (
192
+ <div
193
+ ref={wrapRef}
194
+ className="relative flex h-[28px] w-[260px] shrink-0 items-center justify-center rounded-[6px] border border-border-presentation-state-focus bg-background-presentation-form-field-primary px-1 shadow-[0_1px_6px_0_rgba(0,0,0,0.30)] transition-all duration-150 ease-in-out"
195
+ >
196
+ <input
197
+ ref={inputRef}
198
+ type="text"
199
+ value={value}
200
+ placeholder={placeholder}
201
+ onChange={(e) => onChange(e.target.value)}
202
+ onKeyDown={(e) => {
203
+ if (e.key === "Escape") clearAndCollapse();
204
+ }}
205
+ className="flex-1 bg-transparent text-[14px] leading-none text-white caret-[#1E7AFE] placeholder:text-content-presentation-global-tertiary focus:outline-none"
206
+ />
207
+ <button
208
+ type="button"
209
+ aria-label="Clear search"
210
+ onClick={clearAndCollapse}
211
+ className="flex shrink-0 items-center justify-center self-stretch px-1"
212
+ >
213
+ <svg
214
+ xmlns="http://www.w3.org/2000/svg"
215
+ width="16"
216
+ height="16"
217
+ viewBox="0 0 16 16"
218
+ fill="none"
219
+ >
220
+ <path
221
+ d="M7.99992 14.6666C4.31802 14.6666 1.33325 11.6818 1.33325 7.99992C1.33325 4.31802 4.31802 1.33325 7.99992 1.33325C11.6818 1.33325 14.6666 4.31802 14.6666 7.99992C14.6666 11.6818 11.6818 14.6666 7.99992 14.6666ZM7.99992 7.05712L6.1143 5.17149L5.17149 6.1143L7.05712 7.99992L5.17149 9.88552L6.1143 10.8283L7.99992 8.94272L9.88552 10.8283L10.8283 9.88552L8.94272 7.99992L10.8283 6.1143L9.88552 5.17149L7.99992 7.05712Z"
222
+ fill="white"
223
+ />
224
+ </svg>
225
+ </button>
226
+ </div>
227
+ );
126
228
  }