@sovereignfs/ui 0.33.1 → 0.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +1 -1
  2. package/dist/CheckableListRow.module.css +95 -0
  3. package/dist/IconPicker.module.css +63 -0
  4. package/dist/QuantityStepper.module.css +67 -0
  5. package/dist/SuggestionInput.module.css +103 -0
  6. package/dist/index.d.ts +128 -2
  7. package/dist/index.js +1007 -169
  8. package/package.json +1 -1
  9. package/src/components/CheckableListRow/CheckableListRow.module.css +95 -0
  10. package/src/components/CheckableListRow/CheckableListRow.stories.tsx +99 -0
  11. package/src/components/CheckableListRow/CheckableListRow.tsx +89 -0
  12. package/src/components/Icon/icons/apple.tsx +21 -0
  13. package/src/components/Icon/icons/banana.tsx +21 -0
  14. package/src/components/Icon/icons/beef.tsx +22 -0
  15. package/src/components/Icon/icons/beer.tsx +24 -0
  16. package/src/components/Icon/icons/candy.tsx +24 -0
  17. package/src/components/Icon/icons/carrot.tsx +22 -0
  18. package/src/components/Icon/icons/coffee.tsx +23 -0
  19. package/src/components/Icon/icons/cookie.tsx +25 -0
  20. package/src/components/Icon/icons/croissant.tsx +24 -0
  21. package/src/components/Icon/icons/cup-soda.tsx +23 -0
  22. package/src/components/Icon/icons/drumstick.tsx +21 -0
  23. package/src/components/Icon/icons/egg.tsx +20 -0
  24. package/src/components/Icon/icons/fish.tsx +25 -0
  25. package/src/components/Icon/icons/index.ts +81 -1
  26. package/src/components/Icon/icons/milk.tsx +22 -0
  27. package/src/components/Icon/icons/pizza.tsx +24 -0
  28. package/src/components/Icon/icons/salad.tsx +24 -0
  29. package/src/components/Icon/icons/shopping-basket.tsx +26 -0
  30. package/src/components/Icon/icons/snowflake.tsx +31 -0
  31. package/src/components/Icon/icons/spray-can.tsx +29 -0
  32. package/src/components/Icon/icons/wine.tsx +23 -0
  33. package/src/components/IconPicker/IconPicker.module.css +63 -0
  34. package/src/components/IconPicker/IconPicker.stories.tsx +84 -0
  35. package/src/components/IconPicker/IconPicker.tsx +90 -0
  36. package/src/components/QuantityStepper/QuantityStepper.module.css +67 -0
  37. package/src/components/QuantityStepper/QuantityStepper.stories.tsx +79 -0
  38. package/src/components/QuantityStepper/QuantityStepper.tsx +107 -0
  39. package/src/components/SuggestionInput/SuggestionInput.module.css +103 -0
  40. package/src/components/SuggestionInput/SuggestionInput.stories.tsx +144 -0
  41. package/src/components/SuggestionInput/SuggestionInput.tsx +207 -0
  42. package/src/index.ts +11 -0
  43. package/src/stories/DesignSystemOverview.stories.tsx +107 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sovereignfs/ui",
3
- "version": "0.33.1",
3
+ "version": "0.37.0",
4
4
  "type": "module",
5
5
  "description": "Sovereign Design System — design tokens and React components.",
6
6
  "keywords": [
@@ -0,0 +1,95 @@
1
+ .row {
2
+ display: flex;
3
+ align-items: center;
4
+ gap: var(--sv-space-3);
5
+ width: 100%;
6
+ }
7
+
8
+ .tapTarget {
9
+ display: flex;
10
+ align-items: center;
11
+ gap: var(--sv-space-2);
12
+ flex: 1;
13
+ min-width: 0;
14
+ min-height: var(--sv-touch-target-min);
15
+ cursor: pointer;
16
+ }
17
+
18
+ .tapTarget:focus-visible {
19
+ outline: 2px solid var(--sv-color-focus-ring);
20
+ outline-offset: 2px;
21
+ border-radius: var(--sv-radius-sm);
22
+ }
23
+
24
+ /* Visual box — matches Checkbox.module.css's .box/.checked/.tick. */
25
+ .box {
26
+ --checkbox-box-size: 18px;
27
+ flex-shrink: 0;
28
+ width: var(--checkbox-box-size);
29
+ height: var(--checkbox-box-size);
30
+ border-radius: var(--sv-radius-sm);
31
+ border: 1.5px solid var(--sv-color-border-strong);
32
+ background: var(--sv-color-surface);
33
+ transition:
34
+ background-color 0.15s ease,
35
+ border-color 0.15s ease;
36
+ display: flex;
37
+ align-items: center;
38
+ justify-content: center;
39
+ }
40
+
41
+ .checked {
42
+ background-color: var(--sv-color-accent);
43
+ border-color: var(--sv-color-accent);
44
+ color: var(--sv-white);
45
+ }
46
+
47
+ .tick {
48
+ width: 10px;
49
+ height: 8px;
50
+ pointer-events: none;
51
+ }
52
+
53
+ .icon {
54
+ display: flex;
55
+ align-items: center;
56
+ flex-shrink: 0;
57
+ color: var(--sv-color-text-muted);
58
+ }
59
+
60
+ .label {
61
+ flex: 1;
62
+ min-width: 0;
63
+ font-size: var(--sv-font-size-sm);
64
+ color: var(--sv-color-text-primary);
65
+ overflow: hidden;
66
+ text-overflow: ellipsis;
67
+ white-space: nowrap;
68
+ transition: color 0.15s ease;
69
+ position: relative;
70
+ }
71
+
72
+ .label::after {
73
+ content: '';
74
+ position: absolute;
75
+ left: 0;
76
+ top: 50%;
77
+ width: 100%;
78
+ height: 1.5px;
79
+ background: var(--sv-color-text-muted);
80
+ transform: scaleX(0);
81
+ transform-origin: left center;
82
+ transition: transform 0.2s ease;
83
+ }
84
+
85
+ .struck {
86
+ color: var(--sv-color-text-muted);
87
+ }
88
+
89
+ .struck::after {
90
+ transform: scaleX(1);
91
+ }
92
+
93
+ .trailing {
94
+ flex-shrink: 0;
95
+ }
@@ -0,0 +1,99 @@
1
+ import { useState } from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react-vite';
3
+ import { CheckableListRow } from './CheckableListRow';
4
+ import { Icon } from '../Icon/Icon';
5
+
6
+ const meta = {
7
+ title: 'Components/CheckableListRow',
8
+ component: CheckableListRow,
9
+ parameters: {
10
+ layout: 'padded',
11
+ docs: {
12
+ description: {
13
+ component:
14
+ 'A whole-row tap target that toggles a checked state, with strike-through on the label when checked — for "tap the row to mark it done" lists.',
15
+ },
16
+ },
17
+ },
18
+ args: {
19
+ checked: false,
20
+ onCheckedChange: () => {},
21
+ label: 'Bananas',
22
+ },
23
+ } satisfies Meta<typeof CheckableListRow>;
24
+
25
+ export default meta;
26
+ type Story = StoryObj<typeof meta>;
27
+
28
+ function ControlledRow({
29
+ initial = false,
30
+ icon,
31
+ trailing,
32
+ disabled,
33
+ }: {
34
+ initial?: boolean;
35
+ icon?: boolean;
36
+ trailing?: boolean;
37
+ disabled?: boolean;
38
+ }) {
39
+ const [checked, setChecked] = useState(initial);
40
+ return (
41
+ <div style={{ width: 320 }}>
42
+ <CheckableListRow
43
+ checked={checked}
44
+ onCheckedChange={setChecked}
45
+ label="Bananas"
46
+ icon={icon ? <Icon name="banana" size="md" aria-hidden /> : undefined}
47
+ trailing={trailing ? <span style={{ fontSize: 13, color: '#888' }}>6 pcs</span> : undefined}
48
+ disabled={disabled}
49
+ />
50
+ </div>
51
+ );
52
+ }
53
+
54
+ export const Default: Story = {
55
+ render: () => <ControlledRow />,
56
+ };
57
+
58
+ export const Checked: Story = {
59
+ render: () => <ControlledRow initial />,
60
+ };
61
+
62
+ export const WithIconAndTrailing: Story = {
63
+ render: () => <ControlledRow icon trailing />,
64
+ };
65
+
66
+ export const CheckedWithIconAndTrailing: Story = {
67
+ render: () => <ControlledRow initial icon trailing />,
68
+ };
69
+
70
+ export const Disabled: Story = {
71
+ render: () => <ControlledRow icon trailing disabled />,
72
+ };
73
+
74
+ export const List: Story = {
75
+ name: 'Multiple rows (list context)',
76
+ render: () => {
77
+ const items = ['Bananas', 'Milk', 'Eggs', 'Coffee'];
78
+ const [checkedSet, setCheckedSet] = useState<Set<string>>(new Set(['Milk']));
79
+ return (
80
+ <div style={{ width: 320, display: 'flex', flexDirection: 'column', gap: 4 }}>
81
+ {items.map((item) => (
82
+ <CheckableListRow
83
+ key={item}
84
+ checked={checkedSet.has(item)}
85
+ onCheckedChange={(checked) =>
86
+ setCheckedSet((prev) => {
87
+ const next = new Set(prev);
88
+ if (checked) next.add(item);
89
+ else next.delete(item);
90
+ return next;
91
+ })
92
+ }
93
+ label={item}
94
+ />
95
+ ))}
96
+ </div>
97
+ );
98
+ },
99
+ };
@@ -0,0 +1,89 @@
1
+ 'use client';
2
+
3
+ import type { KeyboardEvent, ReactNode } from 'react';
4
+ import styles from './CheckableListRow.module.css';
5
+
6
+ export interface CheckableListRowProps {
7
+ checked: boolean;
8
+ onCheckedChange: (checked: boolean) => void;
9
+ label: string;
10
+ /** Leading icon, e.g. a per-item `<Icon>`. */
11
+ icon?: ReactNode;
12
+ /** Trailing content, e.g. a quantity, a `QuantityStepper`, or a badge. */
13
+ trailing?: ReactNode;
14
+ disabled?: boolean;
15
+ className?: string;
16
+ }
17
+
18
+ /**
19
+ * CheckableListRow — a whole-row tap target that toggles a checked state,
20
+ * with strike-through on the label when checked. Built for "tap the row to
21
+ * mark it done" lists (Sovereign Shopper's tap-to-buy, SHP-07) where the
22
+ * checkbox itself is too small a target on mobile and the row already has
23
+ * nothing else competing for the tap.
24
+ *
25
+ * Renders as `role="checkbox"` on the row itself rather than composing
26
+ * `Checkbox`'s native `<input>` — nesting a real checkbox input inside the
27
+ * row's own click handler would mean two overlapping interactive elements
28
+ * (invalid HTML, and the input's own click would double-fire the row's
29
+ * toggle). The visual box matches `Checkbox`'s styling for consistency.
30
+ *
31
+ * `trailing` content (e.g. a `QuantityStepper`) is rendered outside the
32
+ * `role="checkbox"` element so its own interactive controls (+/- buttons)
33
+ * don't sit inside another interactive element either — clicking those
34
+ * doesn't toggle the row.
35
+ */
36
+ export function CheckableListRow({
37
+ checked,
38
+ onCheckedChange,
39
+ label,
40
+ icon,
41
+ trailing,
42
+ disabled = false,
43
+ className,
44
+ }: CheckableListRowProps) {
45
+ function toggle() {
46
+ if (!disabled) onCheckedChange(!checked);
47
+ }
48
+
49
+ function handleKeyDown(e: KeyboardEvent<HTMLDivElement>) {
50
+ if (e.key === ' ' || e.key === 'Enter') {
51
+ e.preventDefault();
52
+ toggle();
53
+ }
54
+ }
55
+
56
+ return (
57
+ <div className={[styles.row, className].filter(Boolean).join(' ')}>
58
+ <div
59
+ role="checkbox"
60
+ aria-checked={checked}
61
+ aria-label={label}
62
+ aria-disabled={disabled || undefined}
63
+ tabIndex={disabled ? -1 : 0}
64
+ className={styles.tapTarget}
65
+ onClick={toggle}
66
+ onKeyDown={handleKeyDown}
67
+ >
68
+ <span className={[styles.box, checked ? styles.checked : ''].filter(Boolean).join(' ')}>
69
+ {checked && (
70
+ <svg className={styles.tick} viewBox="0 0 10 8" fill="none" aria-hidden="true">
71
+ <path
72
+ d="M1 4l3 3 5-6"
73
+ stroke="currentColor"
74
+ strokeWidth="1.5"
75
+ strokeLinecap="round"
76
+ strokeLinejoin="round"
77
+ />
78
+ </svg>
79
+ )}
80
+ </span>
81
+ {icon && <span className={styles.icon}>{icon}</span>}
82
+ <span className={[styles.label, checked ? styles.struck : ''].filter(Boolean).join(' ')}>
83
+ {label}
84
+ </span>
85
+ </div>
86
+ {trailing && <span className={styles.trailing}>{trailing}</span>}
87
+ </div>
88
+ );
89
+ }
@@ -0,0 +1,21 @@
1
+ // Generated by scripts/generate-icons.ts — do not edit.
2
+ // Source: Lucide (https://lucide.dev) — ISC license, see packages/ui/NOTICE.
3
+ import type { SVGProps } from 'react';
4
+
5
+ export function AppleIcon(props: SVGProps<SVGSVGElement>) {
6
+ return (
7
+ <svg
8
+ xmlns="http://www.w3.org/2000/svg"
9
+ viewBox="0 0 24 24"
10
+ fill="none"
11
+ stroke="currentColor"
12
+ strokeWidth="2"
13
+ strokeLinecap="round"
14
+ strokeLinejoin="round"
15
+ {...props}
16
+ >
17
+ <path d="M12 6.528V3a1 1 0 0 1 1-1h0" />
18
+ <path d="M18.237 21A15 15 0 0 0 22 11a6 6 0 0 0-10-4.472A6 6 0 0 0 2 11a15.1 15.1 0 0 0 3.763 10 3 3 0 0 0 3.648.648 5.5 5.5 0 0 1 5.178 0A3 3 0 0 0 18.237 21" />
19
+ </svg>
20
+ );
21
+ }
@@ -0,0 +1,21 @@
1
+ // Generated by scripts/generate-icons.ts — do not edit.
2
+ // Source: Lucide (https://lucide.dev) — ISC license, see packages/ui/NOTICE.
3
+ import type { SVGProps } from 'react';
4
+
5
+ export function BananaIcon(props: SVGProps<SVGSVGElement>) {
6
+ return (
7
+ <svg
8
+ xmlns="http://www.w3.org/2000/svg"
9
+ viewBox="0 0 24 24"
10
+ fill="none"
11
+ stroke="currentColor"
12
+ strokeWidth="2"
13
+ strokeLinecap="round"
14
+ strokeLinejoin="round"
15
+ {...props}
16
+ >
17
+ <path d="M4 13c3.5-2 8-2 10 2a5.5 5.5 0 0 1 8 5" />
18
+ <path d="M5.15 17.89c5.52-1.52 8.65-6.89 7-12C11.55 4 11.5 2 13 2c3.22 0 5 5.5 5 8 0 6.5-4.2 12-10.49 12C5.11 22 2 22 2 20c0-1.5 1.14-1.55 3.15-2.11Z" />
19
+ </svg>
20
+ );
21
+ }
@@ -0,0 +1,22 @@
1
+ // Generated by scripts/generate-icons.ts — do not edit.
2
+ // Source: Lucide (https://lucide.dev) — ISC license, see packages/ui/NOTICE.
3
+ import type { SVGProps } from 'react';
4
+
5
+ export function BeefIcon(props: SVGProps<SVGSVGElement>) {
6
+ return (
7
+ <svg
8
+ xmlns="http://www.w3.org/2000/svg"
9
+ viewBox="0 0 24 24"
10
+ fill="none"
11
+ stroke="currentColor"
12
+ strokeWidth="2"
13
+ strokeLinecap="round"
14
+ strokeLinejoin="round"
15
+ {...props}
16
+ >
17
+ <path d="M16.4 13.7A6.5 6.5 0 1 0 6.28 6.6c-1.1 3.13-.78 3.9-3.18 6.08A3 3 0 0 0 5 18c4 0 8.4-1.8 11.4-4.3" />
18
+ <path d="m18.5 6 2.19 4.5a6.48 6.48 0 0 1-2.29 7.2C15.4 20.2 11 22 7 22a3 3 0 0 1-2.68-1.66L2.4 16.5" />
19
+ <circle cx="12.5" cy="8.5" r="2.5" />
20
+ </svg>
21
+ );
22
+ }
@@ -0,0 +1,24 @@
1
+ // Generated by scripts/generate-icons.ts — do not edit.
2
+ // Source: Lucide (https://lucide.dev) — ISC license, see packages/ui/NOTICE.
3
+ import type { SVGProps } from 'react';
4
+
5
+ export function BeerIcon(props: SVGProps<SVGSVGElement>) {
6
+ return (
7
+ <svg
8
+ xmlns="http://www.w3.org/2000/svg"
9
+ viewBox="0 0 24 24"
10
+ fill="none"
11
+ stroke="currentColor"
12
+ strokeWidth="2"
13
+ strokeLinecap="round"
14
+ strokeLinejoin="round"
15
+ {...props}
16
+ >
17
+ <path d="M17 11h1a3 3 0 0 1 0 6h-1" />
18
+ <path d="M9 12v6" />
19
+ <path d="M13 12v6" />
20
+ <path d="M14 7.5c-1 0-1.44.5-3 .5s-2-.5-3-.5-1.72.5-2.5.5a2.5 2.5 0 0 1 0-5c.78 0 1.57.5 2.5.5S9.44 2 11 2s2 1.5 3 1.5 1.72-.5 2.5-.5a2.5 2.5 0 0 1 0 5c-.78 0-1.5-.5-2.5-.5Z" />
21
+ <path d="M5 8v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V8" />
22
+ </svg>
23
+ );
24
+ }
@@ -0,0 +1,24 @@
1
+ // Generated by scripts/generate-icons.ts — do not edit.
2
+ // Source: Lucide (https://lucide.dev) — ISC license, see packages/ui/NOTICE.
3
+ import type { SVGProps } from 'react';
4
+
5
+ export function CandyIcon(props: SVGProps<SVGSVGElement>) {
6
+ return (
7
+ <svg
8
+ xmlns="http://www.w3.org/2000/svg"
9
+ viewBox="0 0 24 24"
10
+ fill="none"
11
+ stroke="currentColor"
12
+ strokeWidth="2"
13
+ strokeLinecap="round"
14
+ strokeLinejoin="round"
15
+ {...props}
16
+ >
17
+ <path d="M10 7v10.9" />
18
+ <path d="M14 6.1V17" />
19
+ <path d="M16 7V3a1 1 0 0 1 1.707-.707 2.5 2.5 0 0 0 2.152.717 1 1 0 0 1 1.131 1.131 2.5 2.5 0 0 0 .717 2.152A1 1 0 0 1 21 8h-4" />
20
+ <path d="M16.536 7.465a5 5 0 0 0-7.072 0l-2 2a5 5 0 0 0 0 7.07 5 5 0 0 0 7.072 0l2-2a5 5 0 0 0 0-7.07" />
21
+ <path d="M8 17v4a1 1 0 0 1-1.707.707 2.5 2.5 0 0 0-2.152-.717 1 1 0 0 1-1.131-1.131 2.5 2.5 0 0 0-.717-2.152A1 1 0 0 1 3 16h4" />
22
+ </svg>
23
+ );
24
+ }
@@ -0,0 +1,22 @@
1
+ // Generated by scripts/generate-icons.ts — do not edit.
2
+ // Source: Lucide (https://lucide.dev) — ISC license, see packages/ui/NOTICE.
3
+ import type { SVGProps } from 'react';
4
+
5
+ export function CarrotIcon(props: SVGProps<SVGSVGElement>) {
6
+ return (
7
+ <svg
8
+ xmlns="http://www.w3.org/2000/svg"
9
+ viewBox="0 0 24 24"
10
+ fill="none"
11
+ stroke="currentColor"
12
+ strokeWidth="2"
13
+ strokeLinecap="round"
14
+ strokeLinejoin="round"
15
+ {...props}
16
+ >
17
+ <path d="M2.27 21.7s9.87-3.5 12.73-6.36a4.5 4.5 0 0 0-6.36-6.37C5.77 11.84 2.27 21.7 2.27 21.7zM8.64 14l-2.05-2.04M15.34 15l-2.46-2.46" />
18
+ <path d="M22 9s-1.33-2-3.5-2C16.86 7 15 9 15 9s1.33 2 3.5 2S22 9 22 9z" />
19
+ <path d="M15 2s-2 1.33-2 3.5S15 9 15 9s2-1.84 2-3.5C17 3.33 15 2 15 2z" />
20
+ </svg>
21
+ );
22
+ }
@@ -0,0 +1,23 @@
1
+ // Generated by scripts/generate-icons.ts — do not edit.
2
+ // Source: Lucide (https://lucide.dev) — ISC license, see packages/ui/NOTICE.
3
+ import type { SVGProps } from 'react';
4
+
5
+ export function CoffeeIcon(props: SVGProps<SVGSVGElement>) {
6
+ return (
7
+ <svg
8
+ xmlns="http://www.w3.org/2000/svg"
9
+ viewBox="0 0 24 24"
10
+ fill="none"
11
+ stroke="currentColor"
12
+ strokeWidth="2"
13
+ strokeLinecap="round"
14
+ strokeLinejoin="round"
15
+ {...props}
16
+ >
17
+ <path d="M10 2v2" />
18
+ <path d="M14 2v2" />
19
+ <path d="M16 8a1 1 0 0 1 1 1v8a4 4 0 0 1-4 4H7a4 4 0 0 1-4-4V9a1 1 0 0 1 1-1h14a4 4 0 1 1 0 8h-1" />
20
+ <path d="M6 2v2" />
21
+ </svg>
22
+ );
23
+ }
@@ -0,0 +1,25 @@
1
+ // Generated by scripts/generate-icons.ts — do not edit.
2
+ // Source: Lucide (https://lucide.dev) — ISC license, see packages/ui/NOTICE.
3
+ import type { SVGProps } from 'react';
4
+
5
+ export function CookieIcon(props: SVGProps<SVGSVGElement>) {
6
+ return (
7
+ <svg
8
+ xmlns="http://www.w3.org/2000/svg"
9
+ viewBox="0 0 24 24"
10
+ fill="none"
11
+ stroke="currentColor"
12
+ strokeWidth="2"
13
+ strokeLinecap="round"
14
+ strokeLinejoin="round"
15
+ {...props}
16
+ >
17
+ <path d="M12 2a10 10 0 1 0 10 10 4 4 0 0 1-5-5 4 4 0 0 1-5-5" />
18
+ <path d="M8.5 8.5v.01" />
19
+ <path d="M16 15.5v.01" />
20
+ <path d="M12 12v.01" />
21
+ <path d="M11 17v.01" />
22
+ <path d="M7 14v.01" />
23
+ </svg>
24
+ );
25
+ }
@@ -0,0 +1,24 @@
1
+ // Generated by scripts/generate-icons.ts — do not edit.
2
+ // Source: Lucide (https://lucide.dev) — ISC license, see packages/ui/NOTICE.
3
+ import type { SVGProps } from 'react';
4
+
5
+ export function CroissantIcon(props: SVGProps<SVGSVGElement>) {
6
+ return (
7
+ <svg
8
+ xmlns="http://www.w3.org/2000/svg"
9
+ viewBox="0 0 24 24"
10
+ fill="none"
11
+ stroke="currentColor"
12
+ strokeWidth="2"
13
+ strokeLinecap="round"
14
+ strokeLinejoin="round"
15
+ {...props}
16
+ >
17
+ <path d="M10.2 18H4.774a1.5 1.5 0 0 1-1.352-.97 11 11 0 0 1 .132-6.487" />
18
+ <path d="M18 10.2V4.774a1.5 1.5 0 0 0-.97-1.352 11 11 0 0 0-6.486.132" />
19
+ <path d="M18 5a4 3 0 0 1 4 3 2 2 0 0 1-2 2 10 10 0 0 0-5.139 1.42" />
20
+ <path d="M5 18a3 4 0 0 0 3 4 2 2 0 0 0 2-2 10 10 0 0 1 1.42-5.14" />
21
+ <path d="M8.709 2.554a10 10 0 0 0-6.155 6.155 1.5 1.5 0 0 0 .676 1.626l9.807 5.42a2 2 0 0 0 2.718-2.718l-5.42-9.807a1.5 1.5 0 0 0-1.626-.676" />
22
+ </svg>
23
+ );
24
+ }
@@ -0,0 +1,23 @@
1
+ // Generated by scripts/generate-icons.ts — do not edit.
2
+ // Source: Lucide (https://lucide.dev) — ISC license, see packages/ui/NOTICE.
3
+ import type { SVGProps } from 'react';
4
+
5
+ export function CupSodaIcon(props: SVGProps<SVGSVGElement>) {
6
+ return (
7
+ <svg
8
+ xmlns="http://www.w3.org/2000/svg"
9
+ viewBox="0 0 24 24"
10
+ fill="none"
11
+ stroke="currentColor"
12
+ strokeWidth="2"
13
+ strokeLinecap="round"
14
+ strokeLinejoin="round"
15
+ {...props}
16
+ >
17
+ <path d="m6 8 1.75 12.28a2 2 0 0 0 2 1.72h4.54a2 2 0 0 0 2-1.72L18 8" />
18
+ <path d="M5 8h14" />
19
+ <path d="M7 15a6.47 6.47 0 0 1 5 0 6.47 6.47 0 0 0 5 0" />
20
+ <path d="m12 8 1-6h2" />
21
+ </svg>
22
+ );
23
+ }
@@ -0,0 +1,21 @@
1
+ // Generated by scripts/generate-icons.ts — do not edit.
2
+ // Source: Lucide (https://lucide.dev) — ISC license, see packages/ui/NOTICE.
3
+ import type { SVGProps } from 'react';
4
+
5
+ export function DrumstickIcon(props: SVGProps<SVGSVGElement>) {
6
+ return (
7
+ <svg
8
+ xmlns="http://www.w3.org/2000/svg"
9
+ viewBox="0 0 24 24"
10
+ fill="none"
11
+ stroke="currentColor"
12
+ strokeWidth="2"
13
+ strokeLinecap="round"
14
+ strokeLinejoin="round"
15
+ {...props}
16
+ >
17
+ <path d="M15.4 15.63a7.875 6 135 1 1 6.23-6.23 4.5 3.43 135 0 0-6.23 6.23" />
18
+ <path d="m8.29 12.71-2.6 2.6a2.5 2.5 0 1 0-1.65 4.65A2.5 2.5 0 1 0 8.7 18.3l2.59-2.59" />
19
+ </svg>
20
+ );
21
+ }
@@ -0,0 +1,20 @@
1
+ // Generated by scripts/generate-icons.ts — do not edit.
2
+ // Source: Lucide (https://lucide.dev) — ISC license, see packages/ui/NOTICE.
3
+ import type { SVGProps } from 'react';
4
+
5
+ export function EggIcon(props: SVGProps<SVGSVGElement>) {
6
+ return (
7
+ <svg
8
+ xmlns="http://www.w3.org/2000/svg"
9
+ viewBox="0 0 24 24"
10
+ fill="none"
11
+ stroke="currentColor"
12
+ strokeWidth="2"
13
+ strokeLinecap="round"
14
+ strokeLinejoin="round"
15
+ {...props}
16
+ >
17
+ <path d="M12 2C8 2 4 8 4 14a8 8 0 0 0 16 0c0-6-4-12-8-12" />
18
+ </svg>
19
+ );
20
+ }
@@ -0,0 +1,25 @@
1
+ // Generated by scripts/generate-icons.ts — do not edit.
2
+ // Source: Lucide (https://lucide.dev) — ISC license, see packages/ui/NOTICE.
3
+ import type { SVGProps } from 'react';
4
+
5
+ export function FishIcon(props: SVGProps<SVGSVGElement>) {
6
+ return (
7
+ <svg
8
+ xmlns="http://www.w3.org/2000/svg"
9
+ viewBox="0 0 24 24"
10
+ fill="none"
11
+ stroke="currentColor"
12
+ strokeWidth="2"
13
+ strokeLinecap="round"
14
+ strokeLinejoin="round"
15
+ {...props}
16
+ >
17
+ <path d="M6.5 12c.94-3.46 4.94-6 8.5-6 3.56 0 6.06 2.54 7 6-.94 3.47-3.44 6-7 6s-7.56-2.53-8.5-6Z" />
18
+ <path d="M18 12v.5" />
19
+ <path d="M16 17.93a9.77 9.77 0 0 1 0-11.86" />
20
+ <path d="M7 10.67C7 8 5.58 5.97 2.73 5.5c-1 1.5-1 5 .23 6.5-1.24 1.5-1.24 5-.23 6.5C5.58 18.03 7 16 7 13.33" />
21
+ <path d="M10.46 7.26C10.2 5.88 9.17 4.24 8 3h5.8a2 2 0 0 1 1.98 1.67l.23 1.4" />
22
+ <path d="m16.01 17.93-.23 1.4A2 2 0 0 1 13.8 21H9.5a5.96 5.96 0 0 0 1.49-3.98" />
23
+ </svg>
24
+ );
25
+ }