panelui-native 0.2.0 → 0.5.1

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 (106) hide show
  1. package/README.md +258 -0
  2. package/lib/module/components/accordion/index.js +312 -0
  3. package/lib/module/components/accordion/index.js.map +1 -0
  4. package/lib/module/components/alert/index.js +106 -13
  5. package/lib/module/components/alert/index.js.map +1 -1
  6. package/lib/module/components/avatar/index.js +58 -17
  7. package/lib/module/components/avatar/index.js.map +1 -1
  8. package/lib/module/components/badge/index.js +29 -8
  9. package/lib/module/components/badge/index.js.map +1 -1
  10. package/lib/module/components/button/index.js +87 -26
  11. package/lib/module/components/button/index.js.map +1 -1
  12. package/lib/module/components/checkbox/index.js +59 -18
  13. package/lib/module/components/checkbox/index.js.map +1 -1
  14. package/lib/module/components/empty-state/index.js +178 -0
  15. package/lib/module/components/empty-state/index.js.map +1 -0
  16. package/lib/module/components/frame/index.js +64 -13
  17. package/lib/module/components/frame/index.js.map +1 -1
  18. package/lib/module/components/input-group/index.js +132 -0
  19. package/lib/module/components/input-group/index.js.map +1 -0
  20. package/lib/module/components/label/index.js +117 -0
  21. package/lib/module/components/label/index.js.map +1 -0
  22. package/lib/module/components/progress/index.js +138 -0
  23. package/lib/module/components/progress/index.js.map +1 -0
  24. package/lib/module/components/steps/index.js +354 -0
  25. package/lib/module/components/steps/index.js.map +1 -0
  26. package/lib/module/components/tabs/index.js +9 -3
  27. package/lib/module/components/tabs/index.js.map +1 -1
  28. package/lib/module/components/timeline/index.js +633 -0
  29. package/lib/module/components/timeline/index.js.map +1 -0
  30. package/lib/module/components/toast/index.js +569 -0
  31. package/lib/module/components/toast/index.js.map +1 -0
  32. package/lib/module/components/toast/toast-store.js +81 -0
  33. package/lib/module/components/toast/toast-store.js.map +1 -0
  34. package/lib/module/components/typography/index.js +126 -0
  35. package/lib/module/components/typography/index.js.map +1 -0
  36. package/lib/module/icons/index.js +590 -8
  37. package/lib/module/icons/index.js.map +1 -1
  38. package/lib/module/index.js +11 -2
  39. package/lib/module/index.js.map +1 -1
  40. package/lib/module/providers/panel-ui-provider.js +2 -1
  41. package/lib/module/providers/panel-ui-provider.js.map +1 -1
  42. package/lib/module/theme/use-theme.js +90 -3
  43. package/lib/module/theme/use-theme.js.map +1 -1
  44. package/lib/typescript/src/components/accordion/index.d.ts +56 -0
  45. package/lib/typescript/src/components/accordion/index.d.ts.map +1 -0
  46. package/lib/typescript/src/components/alert/index.d.ts +56 -4
  47. package/lib/typescript/src/components/alert/index.d.ts.map +1 -1
  48. package/lib/typescript/src/components/avatar/index.d.ts +8 -1
  49. package/lib/typescript/src/components/avatar/index.d.ts.map +1 -1
  50. package/lib/typescript/src/components/badge/index.d.ts +38 -0
  51. package/lib/typescript/src/components/badge/index.d.ts.map +1 -1
  52. package/lib/typescript/src/components/button/index.d.ts +57 -0
  53. package/lib/typescript/src/components/button/index.d.ts.map +1 -1
  54. package/lib/typescript/src/components/checkbox/index.d.ts +50 -0
  55. package/lib/typescript/src/components/checkbox/index.d.ts.map +1 -1
  56. package/lib/typescript/src/components/empty-state/index.d.ts +73 -0
  57. package/lib/typescript/src/components/empty-state/index.d.ts.map +1 -0
  58. package/lib/typescript/src/components/frame/index.d.ts +39 -5
  59. package/lib/typescript/src/components/frame/index.d.ts.map +1 -1
  60. package/lib/typescript/src/components/input-group/index.d.ts +34 -0
  61. package/lib/typescript/src/components/input-group/index.d.ts.map +1 -0
  62. package/lib/typescript/src/components/label/index.d.ts +28 -0
  63. package/lib/typescript/src/components/label/index.d.ts.map +1 -0
  64. package/lib/typescript/src/components/progress/index.d.ts +132 -0
  65. package/lib/typescript/src/components/progress/index.d.ts.map +1 -0
  66. package/lib/typescript/src/components/steps/index.d.ts +62 -0
  67. package/lib/typescript/src/components/steps/index.d.ts.map +1 -0
  68. package/lib/typescript/src/components/tabs/index.d.ts.map +1 -1
  69. package/lib/typescript/src/components/timeline/index.d.ts +96 -0
  70. package/lib/typescript/src/components/timeline/index.d.ts.map +1 -0
  71. package/lib/typescript/src/components/toast/index.d.ts +176 -0
  72. package/lib/typescript/src/components/toast/index.d.ts.map +1 -0
  73. package/lib/typescript/src/components/toast/toast-store.d.ts +65 -0
  74. package/lib/typescript/src/components/toast/toast-store.d.ts.map +1 -0
  75. package/lib/typescript/src/components/typography/index.d.ts +77 -0
  76. package/lib/typescript/src/components/typography/index.d.ts.map +1 -0
  77. package/lib/typescript/src/icons/index.d.ts +60 -0
  78. package/lib/typescript/src/icons/index.d.ts.map +1 -1
  79. package/lib/typescript/src/index.d.ts +13 -4
  80. package/lib/typescript/src/index.d.ts.map +1 -1
  81. package/lib/typescript/src/providers/panel-ui-provider.d.ts.map +1 -1
  82. package/lib/typescript/src/theme/use-theme.d.ts +64 -4
  83. package/lib/typescript/src/theme/use-theme.d.ts.map +1 -1
  84. package/package.json +22 -4
  85. package/src/components/accordion/index.tsx +344 -0
  86. package/src/components/alert/index.tsx +102 -16
  87. package/src/components/avatar/index.tsx +68 -20
  88. package/src/components/badge/index.tsx +38 -9
  89. package/src/components/button/index.tsx +102 -19
  90. package/src/components/checkbox/index.tsx +64 -12
  91. package/src/components/empty-state/index.tsx +136 -0
  92. package/src/components/frame/index.tsx +101 -31
  93. package/src/components/input-group/index.tsx +164 -0
  94. package/src/components/label/index.tsx +128 -0
  95. package/src/components/progress/index.tsx +147 -0
  96. package/src/components/steps/index.tsx +343 -0
  97. package/src/components/tabs/index.tsx +10 -2
  98. package/src/components/timeline/index.tsx +456 -0
  99. package/src/components/toast/index.tsx +568 -0
  100. package/src/components/toast/toast-store.ts +120 -0
  101. package/src/components/typography/index.tsx +121 -0
  102. package/src/icons/index.tsx +423 -7
  103. package/src/index.ts +114 -4
  104. package/src/providers/panel-ui-provider.tsx +3 -0
  105. package/src/theme/use-theme.ts +119 -4
  106. package/theme.css +330 -7
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Typography — semantic text presets.
3
+ *
4
+ * Adapted from: heroui-inc/heroui-native (Typography `type` scale and the
5
+ * Heading / Paragraph / Code compound parts), built on PanelUI's Text
6
+ * primitive so every preset keeps `className` passthrough and theme colours.
7
+ */
8
+ import { forwardRef } from 'react';
9
+ import { View, type Text as RNText, type ViewProps } from 'react-native';
10
+ import { tv, type VariantProps } from 'tailwind-variants';
11
+ import { Text, type TextProps } from '../../primitives/text';
12
+
13
+ const typographyVariants = tv({
14
+ base: 'text-foreground',
15
+ variants: {
16
+ type: {
17
+ h1: 'text-4xl font-bold tracking-tight',
18
+ h2: 'text-3xl font-semibold tracking-tight',
19
+ h3: 'text-2xl font-semibold tracking-tight',
20
+ h4: 'text-xl font-semibold',
21
+ h5: 'text-lg font-semibold',
22
+ h6: 'text-base font-semibold',
23
+ body: 'text-base font-normal',
24
+ 'body-sm': 'text-sm font-normal',
25
+ 'body-xs': 'text-xs font-normal',
26
+ code: 'font-mono text-sm text-foreground',
27
+ },
28
+ muted: {
29
+ true: 'text-muted-foreground',
30
+ },
31
+ },
32
+ defaultVariants: {
33
+ type: 'body',
34
+ },
35
+ });
36
+
37
+ export type TypographyType = NonNullable<
38
+ VariantProps<typeof typographyVariants>['type']
39
+ >;
40
+
41
+ export interface TypographyProps
42
+ extends Omit<TextProps, 'size' | 'weight'>,
43
+ VariantProps<typeof typographyVariants> {
44
+ className?: string;
45
+ }
46
+
47
+ /** Heading levels, for `Typography.Heading`. */
48
+ type HeadingType = Extract<TypographyType, 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'>;
49
+ /** Body sizes, for `Typography.Paragraph`. */
50
+ type ParagraphType = Extract<TypographyType, 'body' | 'body-sm' | 'body-xs'>;
51
+
52
+ /** Maps a heading preset to its accessibility heading level. */
53
+ const HEADING_LEVEL: Record<HeadingType, number> = {
54
+ h1: 1,
55
+ h2: 2,
56
+ h3: 3,
57
+ h4: 4,
58
+ h5: 5,
59
+ h6: 6,
60
+ };
61
+
62
+ const TypographyRoot = forwardRef<RNText, TypographyProps>(
63
+ ({ className, type, muted, ...props }, ref) => (
64
+ <Text ref={ref} className={typographyVariants({ type, muted, className })} {...props} />
65
+ )
66
+ );
67
+ TypographyRoot.displayName = 'Typography';
68
+
69
+ export interface TypographyHeadingProps extends Omit<TypographyProps, 'type'> {
70
+ type?: HeadingType;
71
+ }
72
+
73
+ /** Heading text, wired up with the matching accessibility heading level. */
74
+ const TypographyHeading = forwardRef<RNText, TypographyHeadingProps>(
75
+ ({ className, type = 'h2', muted, ...props }, ref) => (
76
+ <Text
77
+ ref={ref}
78
+ accessibilityRole="header"
79
+ aria-level={HEADING_LEVEL[type]}
80
+ className={typographyVariants({ type, muted, className })}
81
+ {...props}
82
+ />
83
+ )
84
+ );
85
+ TypographyHeading.displayName = 'Typography.Heading';
86
+
87
+ export interface TypographyParagraphProps extends Omit<TypographyProps, 'type'> {
88
+ type?: ParagraphType;
89
+ }
90
+
91
+ const TypographyParagraph = forwardRef<RNText, TypographyParagraphProps>(
92
+ ({ className, type = 'body', muted, ...props }, ref) => (
93
+ <Text ref={ref} className={typographyVariants({ type, muted, className })} {...props} />
94
+ )
95
+ );
96
+ TypographyParagraph.displayName = 'Typography.Paragraph';
97
+
98
+ export interface TypographyCodeProps extends Omit<TypographyProps, 'type'> {
99
+ /** Classes for the surface behind the code text. */
100
+ containerClassName?: string;
101
+ }
102
+
103
+ /** Inline code on a muted surface. */
104
+ const TypographyCode = forwardRef<View, TypographyCodeProps & Pick<ViewProps, 'testID'>>(
105
+ ({ className, containerClassName, muted, testID, ...props }, ref) => (
106
+ <View
107
+ ref={ref}
108
+ testID={testID}
109
+ className={`self-start rounded-md bg-muted px-1.5 py-1 ${containerClassName ?? ''}`}
110
+ >
111
+ <Text className={typographyVariants({ type: 'code', muted, className })} {...props} />
112
+ </View>
113
+ )
114
+ );
115
+ TypographyCode.displayName = 'Typography.Code';
116
+
117
+ export const Typography = Object.assign(TypographyRoot, {
118
+ Heading: TypographyHeading,
119
+ Paragraph: TypographyParagraph,
120
+ Code: TypographyCode,
121
+ });
@@ -1,16 +1,77 @@
1
- import Svg, { Path, type SvgProps } from 'react-native-svg';
1
+ /**
2
+ * Icon set.
3
+ *
4
+ * Two families live here:
5
+ * - Stroked 24×24 icons (Lucide geometry, as used by shadcn-ui/ui) for chrome
6
+ * such as chevrons and the close button.
7
+ * - Filled 16×16 status icons for Alert and Toast indicators.
8
+ * Adapted from: heroui-inc/heroui-native src/components/alert/{default,success,warning}-icon.tsx
9
+ *
10
+ * Every icon resolves its colour in the same order: an explicit `color` prop,
11
+ * then the colour inherited from an enclosing `IconColorProvider`, then its
12
+ * own fallback. Coloured surfaces such as Button provide the foreground that
13
+ * reads against them, so icons follow the theme without callers hardcoding a
14
+ * hex — which breaks the moment the theme inverts.
15
+ *
16
+ * Brand marks (Google, Facebook, Apple) are the exception: they carry their
17
+ * own colours and ignore the context.
18
+ */
19
+ import { createContext, useContext, type ReactNode } from 'react';
20
+ import Svg, { Circle, G, Path, type SvgProps } from 'react-native-svg';
2
21
 
3
22
  export interface IconProps extends SvgProps {
4
23
  size?: number;
5
24
  color?: string;
6
25
  }
7
26
 
8
- export function CheckIcon({ size = 14, color = '#fff', ...props }: IconProps) {
27
+ /**
28
+ * The colour icons inherit when they are not given one explicitly.
29
+ *
30
+ * Coloured surfaces (Button, and anything else that paints its own
31
+ * background) provide the foreground that reads against them, so an icon
32
+ * dropped into one follows the theme without the caller hardcoding a hex —
33
+ * which is what breaks the moment the theme inverts.
34
+ */
35
+ const IconColorContext = createContext<string | undefined>(undefined);
36
+
37
+ export function IconColorProvider({
38
+ color,
39
+ children,
40
+ }: {
41
+ color: string | undefined;
42
+ children: ReactNode;
43
+ }) {
44
+ return <IconColorContext.Provider value={color}>{children}</IconColorContext.Provider>;
45
+ }
46
+
47
+ /** The inherited icon colour, if a surface is providing one. */
48
+ export function useIconColor(): string | undefined {
49
+ return useContext(IconColorContext);
50
+ }
51
+
52
+ /** Resolves an icon's colour: explicit prop, then inherited, then fallback. */
53
+ function useResolvedColor(explicit: string | undefined, fallback: string): string {
54
+ const inherited = useIconColor();
55
+ return explicit ?? inherited ?? fallback;
56
+ }
57
+
58
+ /** Props for icons that must never be announced by a screen reader. */
59
+ const decorative = {
60
+ accessibilityElementsHidden: true,
61
+ importantForAccessibility: 'no-hide-descendants',
62
+ } as const;
63
+
64
+ /* -------------------------------------------------------------------------- */
65
+ /* Stroked chrome icons */
66
+ /* -------------------------------------------------------------------------- */
67
+
68
+ export function CheckIcon({ size = 14, color, ...props }: IconProps) {
69
+ const resolved = useResolvedColor(color, '#fff');
9
70
  return (
10
71
  <Svg width={size} height={size} viewBox="0 0 24 24" fill="none" {...props}>
11
72
  <Path
12
73
  d="M20 6 9 17l-5-5"
13
- stroke={color}
74
+ stroke={resolved}
14
75
  strokeWidth={3}
15
76
  strokeLinecap="round"
16
77
  strokeLinejoin="round"
@@ -19,12 +80,28 @@ export function CheckIcon({ size = 14, color = '#fff', ...props }: IconProps) {
19
80
  );
20
81
  }
21
82
 
22
- export function ChevronDownIcon({ size = 16, color = '#737373', ...props }: IconProps) {
83
+ export function ChevronDownIcon({ size = 16, color, ...props }: IconProps) {
84
+ const resolved = useResolvedColor(color, '#737373');
23
85
  return (
24
86
  <Svg width={size} height={size} viewBox="0 0 24 24" fill="none" {...props}>
25
87
  <Path
26
88
  d="m6 9 6 6 6-6"
27
- stroke={color}
89
+ stroke={resolved}
90
+ strokeWidth={2}
91
+ strokeLinecap="round"
92
+ strokeLinejoin="round"
93
+ />
94
+ </Svg>
95
+ );
96
+ }
97
+
98
+ export function ChevronLeftIcon({ size = 16, color, ...props }: IconProps) {
99
+ const resolved = useResolvedColor(color, '#737373');
100
+ return (
101
+ <Svg width={size} height={size} viewBox="0 0 24 24" fill="none" {...props}>
102
+ <Path
103
+ d="m15 18-6-6 6-6"
104
+ stroke={resolved}
28
105
  strokeWidth={2}
29
106
  strokeLinecap="round"
30
107
  strokeLinejoin="round"
@@ -33,12 +110,276 @@ export function ChevronDownIcon({ size = 16, color = '#737373', ...props }: Icon
33
110
  );
34
111
  }
35
112
 
36
- export function XIcon({ size = 16, color = '#737373', ...props }: IconProps) {
113
+ export function ChevronRightIcon({ size = 16, color, ...props }: IconProps) {
114
+ const resolved = useResolvedColor(color, '#737373');
115
+ return (
116
+ <Svg width={size} height={size} viewBox="0 0 24 24" fill="none" {...props}>
117
+ <Path
118
+ d="m9 18 6-6-6-6"
119
+ stroke={resolved}
120
+ strokeWidth={2}
121
+ strokeLinecap="round"
122
+ strokeLinejoin="round"
123
+ />
124
+ </Svg>
125
+ );
126
+ }
127
+
128
+ export function XIcon({ size = 16, color, ...props }: IconProps) {
129
+ const resolved = useResolvedColor(color, '#737373');
37
130
  return (
38
131
  <Svg width={size} height={size} viewBox="0 0 24 24" fill="none" {...props}>
39
132
  <Path
40
133
  d="M18 6 6 18M6 6l12 12"
41
- stroke={color}
134
+ stroke={resolved}
135
+ strokeWidth={2}
136
+ strokeLinecap="round"
137
+ strokeLinejoin="round"
138
+ />
139
+ </Svg>
140
+ );
141
+ }
142
+
143
+ export function SearchIcon({ size = 16, color, ...props }: IconProps) {
144
+ const resolved = useResolvedColor(color, '#737373');
145
+ return (
146
+ <Svg width={size} height={size} viewBox="0 0 24 24" fill="none" {...props}>
147
+ <Circle cx={11} cy={11} r={8} stroke={resolved} strokeWidth={2} />
148
+ <Path
149
+ d="m21 21-4.3-4.3"
150
+ stroke={resolved}
151
+ strokeWidth={2}
152
+ strokeLinecap="round"
153
+ strokeLinejoin="round"
154
+ />
155
+ </Svg>
156
+ );
157
+ }
158
+
159
+ export function ArrowUpRightIcon({ size = 20, color, ...props }: IconProps) {
160
+ const resolved = useResolvedColor(color, '#fff');
161
+ return (
162
+ <Svg width={size} height={size} viewBox="0 0 24 24" fill="none" {...props}>
163
+ <Path
164
+ d="M7 17 17 7M8 7h9v9"
165
+ stroke={resolved}
166
+ strokeWidth={2}
167
+ strokeLinecap="round"
168
+ strokeLinejoin="round"
169
+ />
170
+ </Svg>
171
+ );
172
+ }
173
+
174
+ export function SunIcon({ size = 18, color, ...props }: IconProps) {
175
+ const resolved = useResolvedColor(color, '#f5f5f5');
176
+ return (
177
+ <Svg width={size} height={size} viewBox="0 0 24 24" fill="none" {...props}>
178
+ <Circle cx={12} cy={12} r={4} stroke={resolved} strokeWidth={2} />
179
+ <Path
180
+ d="M12 2v2m0 16v2M4.93 4.93l1.41 1.41m11.32 11.32 1.41 1.41M2 12h2m16 0h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"
181
+ stroke={resolved}
182
+ strokeWidth={2}
183
+ strokeLinecap="round"
184
+ />
185
+ </Svg>
186
+ );
187
+ }
188
+
189
+ export function MoonIcon({ size = 18, color, ...props }: IconProps) {
190
+ const resolved = useResolvedColor(color, '#262626');
191
+ return (
192
+ <Svg width={size} height={size} viewBox="0 0 24 24" fill="none" {...props}>
193
+ <Path
194
+ d="M21 12.79A9 9 0 1 1 11.21 3a7 7 0 0 0 9.79 9.79"
195
+ stroke={resolved}
196
+ strokeWidth={2}
197
+ strokeLinecap="round"
198
+ strokeLinejoin="round"
199
+ />
200
+ </Svg>
201
+ );
202
+ }
203
+
204
+ /* -------------------------------------------------------------------------- */
205
+ /* Filled status icons (Alert / Toast indicators) */
206
+ /* -------------------------------------------------------------------------- */
207
+
208
+ /** Info circle. Used for `default`, `info` and `destructive` status. */
209
+ export function InfoIcon({ size = 20, color, ...props }: IconProps) {
210
+ const resolved = useResolvedColor(color, 'currentColor');
211
+ return (
212
+ <Svg width={size} height={size} viewBox="0 0 16 16" fill={resolved} {...decorative} {...props}>
213
+ <Path
214
+ d="M8 13.5a5.5 5.5 0 1 0 0-11a5.5 5.5 0 0 0 0 11M8 15A7 7 0 1 0 8 1a7 7 0 0 0 0 14m1-9.5a1 1 0 1 1-2 0a1 1 0 0 1 2 0m-.25 3a.75.75 0 0 0-1.5 0V11a.75.75 0 0 0 1.5 0z"
215
+ fillRule="evenodd"
216
+ clipRule="evenodd"
217
+ />
218
+ </Svg>
219
+ );
220
+ }
221
+
222
+ /** Check circle. Used for `success` status. */
223
+ export function CheckCircleIcon({ size = 20, color, ...props }: IconProps) {
224
+ const resolved = useResolvedColor(color, 'currentColor');
225
+ return (
226
+ <Svg width={size} height={size} viewBox="0 0 16 16" fill={resolved} {...decorative} {...props}>
227
+ <Path
228
+ d="M13.5 8a5.5 5.5 0 1 1-11 0a5.5 5.5 0 0 1 11 0M15 8A7 7 0 1 1 1 8a7 7 0 0 1 14 0m-3.9-1.55a.75.75 0 1 0-1.2-.9L7.419 8.858L6.03 7.47a.75.75 0 0 0-1.06 1.06l2 2a.75.75 0 0 0 1.13-.08z"
229
+ fillRule="evenodd"
230
+ clipRule="evenodd"
231
+ />
232
+ </Svg>
233
+ );
234
+ }
235
+
236
+ /** Warning triangle. Used for `warning` status. */
237
+ export function AlertTriangleIcon({ size = 20, color, ...props }: IconProps) {
238
+ const resolved = useResolvedColor(color, 'currentColor');
239
+ return (
240
+ <Svg width={size} height={size} viewBox="0 0 16 16" fill={resolved} {...decorative} {...props}>
241
+ <Path
242
+ d="M7.134 2.994L2.217 11.5a1 1 0 0 0 .866 1.5h9.834a1 1 0 0 0 .866-1.5L8.866 2.993a1 1 0 0 0-1.732 0m3.03-.75c-.962-1.665-3.366-1.665-4.329 0L.918 10.749c-.963 1.666.24 3.751 2.165 3.751h9.834c1.925 0 3.128-2.085 2.164-3.751zM8 5a.75.75 0 0 1 .75.75v2a.75.75 0 0 1-1.5 0v-2A.75.75 0 0 1 8 5m1 5.75a1 1 0 1 1-2 0a1 1 0 0 1 2 0"
243
+ fillRule="evenodd"
244
+ clipRule="evenodd"
245
+ />
246
+ </Svg>
247
+ );
248
+ }
249
+
250
+ /* -------------------------------------------------------------------------- */
251
+ /* Brand marks */
252
+ /* -------------------------------------------------------------------------- */
253
+
254
+ /*
255
+ * These keep their official colours and so opt out of the icon colour
256
+ * context — recolouring a brand mark to match a button is a trademark
257
+ * problem, not a theming one.
258
+ */
259
+
260
+ /** Google "G", in the four official brand colours. */
261
+ export function GoogleIcon({ size = 18, ...props }: Omit<IconProps, 'color'>) {
262
+ return (
263
+ <Svg width={size} height={size} viewBox="0 0 24 24" {...decorative} {...props}>
264
+ <G>
265
+ <Path
266
+ fill="#4285F4"
267
+ d="M23.52 12.27c0-.79-.07-1.54-.2-2.27H12v4.51h6.47a5.53 5.53 0 0 1-2.4 3.63v3h3.88c2.27-2.09 3.57-5.17 3.57-8.87"
268
+ />
269
+ <Path
270
+ fill="#34A853"
271
+ d="M12 24c3.24 0 5.96-1.08 7.95-2.91l-3.88-3.01c-1.08.72-2.45 1.15-4.07 1.15-3.13 0-5.78-2.11-6.73-4.96H1.29v3.11A12 12 0 0 0 12 24"
272
+ />
273
+ <Path
274
+ fill="#FBBC05"
275
+ d="M5.27 14.27a7.2 7.2 0 0 1 0-4.54V6.62H1.29a12 12 0 0 0 0 10.76z"
276
+ />
277
+ <Path
278
+ fill="#EA4335"
279
+ d="M12 4.75c1.77 0 3.35.61 4.6 1.8l3.44-3.44C17.95 1.18 15.24 0 12 0A12 12 0 0 0 1.29 6.62l3.98 3.11C6.22 6.86 8.87 4.75 12 4.75"
280
+ />
281
+ </G>
282
+ </Svg>
283
+ );
284
+ }
285
+
286
+ /** Facebook "f" mark. */
287
+ export function FacebookIcon({ size = 18, ...props }: Omit<IconProps, 'color'>) {
288
+ return (
289
+ <Svg width={size} height={size} viewBox="0 0 24 24" {...decorative} {...props}>
290
+ <Path
291
+ fill="#1877F2"
292
+ d="M24 12.07C24 5.4 18.63 0 12 0S0 5.4 0 12.07C0 18.1 4.39 23.09 10.13 24v-8.44H7.08v-3.49h3.05V9.41c0-3.02 1.79-4.69 4.53-4.69 1.31 0 2.68.24 2.68.24v2.97h-1.51c-1.49 0-1.96.93-1.96 1.89v2.25h3.33l-.53 3.49h-2.8V24C19.61 23.09 24 18.1 24 12.07"
293
+ />
294
+ </Svg>
295
+ );
296
+ }
297
+
298
+ /**
299
+ * Apple mark. Monochrome by design, so unlike the other brand marks it does
300
+ * follow the icon colour context — Apple's guidelines require it to match the
301
+ * button's text colour.
302
+ */
303
+ export function AppleIcon({ size = 18, color, ...props }: IconProps) {
304
+ const resolved = useResolvedColor(color, '#000000');
305
+ return (
306
+ <Svg width={size} height={size} viewBox="0 0 24 24" {...decorative} {...props}>
307
+ <Path
308
+ fill={resolved}
309
+ d="M17.05 12.54c-.03-2.85 2.33-4.22 2.43-4.29-1.32-1.94-3.38-2.2-4.11-2.23-1.75-.18-3.42 1.03-4.31 1.03-.89 0-2.26-1.01-3.72-.98-1.91.03-3.68 1.11-4.66 2.82-1.99 3.45-.51 8.55 1.42 11.35.95 1.37 2.07 2.91 3.55 2.85 1.43-.06 1.97-.92 3.69-.92 1.72 0 2.21.92 3.72.89 1.54-.03 2.51-1.39 3.44-2.77 1.09-1.59 1.53-3.13 1.56-3.21-.03-.01-2.99-1.15-3.01-4.54M14.27 4.2c.79-.96 1.32-2.28 1.17-3.6-1.14.05-2.51.76-3.32 1.71-.73.85-1.37 2.2-1.2 3.5 1.27.1 2.57-.65 3.35-1.61"
310
+ />
311
+ </Svg>
312
+ );
313
+ }
314
+
315
+ /* -------------------------------------------------------------------------- */
316
+ /* Event icons (Timeline and other status surfaces) */
317
+ /* -------------------------------------------------------------------------- */
318
+
319
+ export function PlusSquareIcon({ size = 16, color, ...props }: IconProps) {
320
+ const resolved = useResolvedColor(color, '#737373');
321
+ return (
322
+ <Svg width={size} height={size} viewBox="0 0 24 24" fill="none" {...props}>
323
+ <Path
324
+ d="M4 6a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2zM12 8v8M8 12h8"
325
+ stroke={resolved}
326
+ strokeWidth={2}
327
+ strokeLinecap="round"
328
+ strokeLinejoin="round"
329
+ />
330
+ </Svg>
331
+ );
332
+ }
333
+
334
+ /** Three connected nodes — a branch, a share, a fan-out. */
335
+ export function ShareNodesIcon({ size = 16, color, ...props }: IconProps) {
336
+ const resolved = useResolvedColor(color, '#737373');
337
+ return (
338
+ <Svg width={size} height={size} viewBox="0 0 24 24" fill="none" {...props}>
339
+ <Circle cx={18} cy={5} r={2.5} stroke={resolved} strokeWidth={2} />
340
+ <Circle cx={6} cy={12} r={2.5} stroke={resolved} strokeWidth={2} />
341
+ <Circle cx={18} cy={19} r={2.5} stroke={resolved} strokeWidth={2} />
342
+ <Path
343
+ d="m8.6 10.7 6.8-4M8.6 13.3l6.8 4"
344
+ stroke={resolved}
345
+ strokeWidth={2}
346
+ strokeLinecap="round"
347
+ />
348
+ </Svg>
349
+ );
350
+ }
351
+
352
+ /** Shield with an exclamation — a tripped guardrail. */
353
+ export function ShieldAlertIcon({ size = 16, color, ...props }: IconProps) {
354
+ const resolved = useResolvedColor(color, '#737373');
355
+ return (
356
+ <Svg width={size} height={size} viewBox="0 0 24 24" fill="none" {...props}>
357
+ <Path
358
+ d="M12 2.5 4.5 5.5v6c0 4.6 3.2 8.6 7.5 10 4.3-1.4 7.5-5.4 7.5-10v-6z"
359
+ stroke={resolved}
360
+ strokeWidth={2}
361
+ strokeLinejoin="round"
362
+ />
363
+ <Path d="M12 8v4" stroke={resolved} strokeWidth={2} strokeLinecap="round" />
364
+ <Circle cx={12} cy={15.5} r={1} fill={resolved} />
365
+ </Svg>
366
+ );
367
+ }
368
+
369
+ /** Shield with a check — a passed verification. */
370
+ export function ShieldCheckIcon({ size = 16, color, ...props }: IconProps) {
371
+ const resolved = useResolvedColor(color, '#737373');
372
+ return (
373
+ <Svg width={size} height={size} viewBox="0 0 24 24" fill="none" {...props}>
374
+ <Path
375
+ d="M12 2.5 4.5 5.5v6c0 4.6 3.2 8.6 7.5 10 4.3-1.4 7.5-5.4 7.5-10v-6z"
376
+ stroke={resolved}
377
+ strokeWidth={2}
378
+ strokeLinejoin="round"
379
+ />
380
+ <Path
381
+ d="m9 12 2 2 4-4"
382
+ stroke={resolved}
42
383
  strokeWidth={2}
43
384
  strokeLinecap="round"
44
385
  strokeLinejoin="round"
@@ -46,3 +387,78 @@ export function XIcon({ size = 16, color = '#737373', ...props }: IconProps) {
46
387
  </Svg>
47
388
  );
48
389
  }
390
+
391
+ export function BellIcon({ size = 16, color, ...props }: IconProps) {
392
+ const resolved = useResolvedColor(color, '#737373');
393
+ return (
394
+ <Svg width={size} height={size} viewBox="0 0 24 24" fill="none" {...props}>
395
+ <Path
396
+ d="M18 8a6 6 0 1 0-12 0c0 7-3 9-3 9h18s-3-2-3-9M13.7 21a2 2 0 0 1-3.4 0"
397
+ stroke={resolved}
398
+ strokeWidth={2}
399
+ strokeLinecap="round"
400
+ strokeLinejoin="round"
401
+ />
402
+ </Svg>
403
+ );
404
+ }
405
+
406
+ export function PackageIcon({ size = 16, color, ...props }: IconProps) {
407
+ const resolved = useResolvedColor(color, '#737373');
408
+ return (
409
+ <Svg width={size} height={size} viewBox="0 0 24 24" fill="none" {...props}>
410
+ <Path
411
+ d="m12 2.5 8 4.5v10l-8 4.5-8-4.5V7zM4 7l8 4.5L20 7M12 11.5V21"
412
+ stroke={resolved}
413
+ strokeWidth={2}
414
+ strokeLinecap="round"
415
+ strokeLinejoin="round"
416
+ />
417
+ </Svg>
418
+ );
419
+ }
420
+
421
+ export function CardIcon({ size = 16, color, ...props }: IconProps) {
422
+ const resolved = useResolvedColor(color, '#737373');
423
+ return (
424
+ <Svg width={size} height={size} viewBox="0 0 24 24" fill="none" {...props}>
425
+ <Path
426
+ d="M3 7a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2zM3 10h18"
427
+ stroke={resolved}
428
+ strokeWidth={2}
429
+ strokeLinecap="round"
430
+ strokeLinejoin="round"
431
+ />
432
+ </Svg>
433
+ );
434
+ }
435
+
436
+ export function ReceiptIcon({ size = 16, color, ...props }: IconProps) {
437
+ const resolved = useResolvedColor(color, '#737373');
438
+ return (
439
+ <Svg width={size} height={size} viewBox="0 0 24 24" fill="none" {...props}>
440
+ <Path
441
+ d="M5 3h14v18l-2.3-1.6L14.4 21l-2.4-1.6L9.6 21l-2.3-1.6L5 21zM9 8h6M9 12h6"
442
+ stroke={resolved}
443
+ strokeWidth={2}
444
+ strokeLinecap="round"
445
+ strokeLinejoin="round"
446
+ />
447
+ </Svg>
448
+ );
449
+ }
450
+
451
+ /** Paper plane — sent, submitted, approved-and-forwarded. */
452
+ export function SendIcon({ size = 16, color, ...props }: IconProps) {
453
+ const resolved = useResolvedColor(color, '#737373');
454
+ return (
455
+ <Svg width={size} height={size} viewBox="0 0 24 24" fill="none" {...props}>
456
+ <Path
457
+ d="M21.5 2.5 2.5 10l7.5 3 3 7.5z"
458
+ stroke={resolved}
459
+ strokeWidth={2}
460
+ strokeLinejoin="round"
461
+ />
462
+ </Svg>
463
+ );
464
+ }