@cdx-ui/components 0.0.1-beta.70 → 0.0.1-beta.72
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/lib/commonjs/components/Alert/index.js +263 -0
- package/lib/commonjs/components/Alert/index.js.map +1 -0
- package/lib/commonjs/components/Alert/styles.js +87 -0
- package/lib/commonjs/components/Alert/styles.js.map +1 -0
- package/lib/commonjs/components/QuickActionButton/index.js +133 -0
- package/lib/commonjs/components/QuickActionButton/index.js.map +1 -0
- package/lib/commonjs/components/QuickActionButton/styles.js +17 -0
- package/lib/commonjs/components/QuickActionButton/styles.js.map +1 -0
- package/lib/commonjs/components/index.js +24 -0
- package/lib/commonjs/components/index.js.map +1 -1
- package/lib/commonjs/figma/Alert.Button.figma.js +31 -0
- package/lib/commonjs/figma/Alert.Button.figma.js.map +1 -0
- package/lib/commonjs/figma/Alert.Close.figma.js +24 -0
- package/lib/commonjs/figma/Alert.Close.figma.js.map +1 -0
- package/lib/commonjs/figma/Alert.Description.figma.js +20 -0
- package/lib/commonjs/figma/Alert.Description.figma.js.map +1 -0
- package/lib/commonjs/figma/Alert.Title.figma.js +20 -0
- package/lib/commonjs/figma/Alert.Title.figma.js.map +1 -0
- package/lib/commonjs/figma/Alert.figma.js +42 -0
- package/lib/commonjs/figma/Alert.figma.js.map +1 -0
- package/lib/commonjs/figma/QuickActionButton.figma.js +38 -0
- package/lib/commonjs/figma/QuickActionButton.figma.js.map +1 -0
- package/lib/module/components/Alert/index.js +259 -0
- package/lib/module/components/Alert/index.js.map +1 -0
- package/lib/module/components/Alert/styles.js +84 -0
- package/lib/module/components/Alert/styles.js.map +1 -0
- package/lib/module/components/QuickActionButton/index.js +129 -0
- package/lib/module/components/QuickActionButton/index.js.map +1 -0
- package/lib/module/components/QuickActionButton/styles.js +13 -0
- package/lib/module/components/QuickActionButton/styles.js.map +1 -0
- package/lib/module/components/index.js +2 -0
- package/lib/module/components/index.js.map +1 -1
- package/lib/module/figma/Alert.Button.figma.js +25 -0
- package/lib/module/figma/Alert.Button.figma.js.map +1 -0
- package/lib/module/figma/Alert.Close.figma.js +18 -0
- package/lib/module/figma/Alert.Close.figma.js.map +1 -0
- package/lib/module/figma/Alert.Description.figma.js +14 -0
- package/lib/module/figma/Alert.Description.figma.js.map +1 -0
- package/lib/module/figma/Alert.Title.figma.js +14 -0
- package/lib/module/figma/Alert.Title.figma.js.map +1 -0
- package/lib/module/figma/Alert.figma.js +36 -0
- package/lib/module/figma/Alert.figma.js.map +1 -0
- package/lib/module/figma/QuickActionButton.figma.js +32 -0
- package/lib/module/figma/QuickActionButton.figma.js.map +1 -0
- package/lib/typescript/components/Alert/index.d.ts +67 -0
- package/lib/typescript/components/Alert/index.d.ts.map +1 -0
- package/lib/typescript/components/Alert/styles.d.ts +19 -0
- package/lib/typescript/components/Alert/styles.d.ts.map +1 -0
- package/lib/typescript/components/Button/styles.d.ts +4 -4
- package/lib/typescript/components/Chip/styles.d.ts +3 -3
- package/lib/typescript/components/IconButton/styles.d.ts +2 -2
- package/lib/typescript/components/QuickActionButton/index.d.ts +41 -0
- package/lib/typescript/components/QuickActionButton/index.d.ts.map +1 -0
- package/lib/typescript/components/QuickActionButton/styles.d.ts +7 -0
- package/lib/typescript/components/QuickActionButton/styles.d.ts.map +1 -0
- package/lib/typescript/components/Tile/styles.d.ts +1 -1
- package/lib/typescript/components/index.d.ts +2 -0
- package/lib/typescript/components/index.d.ts.map +1 -1
- package/lib/typescript/figma/Alert.Button.figma.d.ts +11 -0
- package/lib/typescript/figma/Alert.Button.figma.d.ts.map +1 -0
- package/lib/typescript/figma/Alert.Close.figma.d.ts +11 -0
- package/lib/typescript/figma/Alert.Close.figma.d.ts.map +1 -0
- package/lib/typescript/figma/Alert.Description.figma.d.ts +8 -0
- package/lib/typescript/figma/Alert.Description.figma.d.ts.map +1 -0
- package/lib/typescript/figma/Alert.Title.figma.d.ts +8 -0
- package/lib/typescript/figma/Alert.Title.figma.d.ts.map +1 -0
- package/lib/typescript/figma/Alert.figma.d.ts +8 -0
- package/lib/typescript/figma/Alert.figma.d.ts.map +1 -0
- package/lib/typescript/figma/QuickActionButton.figma.d.ts +8 -0
- package/lib/typescript/figma/QuickActionButton.figma.d.ts.map +1 -0
- package/package.json +4 -4
- package/src/components/Alert/index.tsx +318 -0
- package/src/components/Alert/styles.ts +88 -0
- package/src/components/QuickActionButton/index.tsx +161 -0
- package/src/components/QuickActionButton/styles.ts +42 -0
- package/src/components/index.ts +2 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import figma from 'figma';
|
|
2
|
+
declare const _default: {
|
|
3
|
+
id: string;
|
|
4
|
+
imports: string[];
|
|
5
|
+
metadata: {
|
|
6
|
+
nestable: boolean;
|
|
7
|
+
};
|
|
8
|
+
example: figma.ResultSection[] | figma.TemplateStringResult | null;
|
|
9
|
+
};
|
|
10
|
+
export default _default;
|
|
11
|
+
//# sourceMappingURL=Alert.Button.figma.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Alert.Button.figma.d.ts","sourceRoot":"","sources":["../../../src/figma/Alert.Button.figma.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,OAAO,CAAC;;;;;;;;;AAa1B,wBAYE"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import figma from 'figma';
|
|
2
|
+
declare const _default: {
|
|
3
|
+
id: string;
|
|
4
|
+
imports: string[];
|
|
5
|
+
metadata: {
|
|
6
|
+
nestable: boolean;
|
|
7
|
+
};
|
|
8
|
+
example: figma.ResultSection[] | figma.TemplateStringResult;
|
|
9
|
+
};
|
|
10
|
+
export default _default;
|
|
11
|
+
//# sourceMappingURL=Alert.Close.figma.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Alert.Close.figma.d.ts","sourceRoot":"","sources":["../../../src/figma/Alert.Close.figma.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,OAAO,CAAC;;;;;;;;;AAQ1B,wBAUE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Alert.Description.figma.d.ts","sourceRoot":"","sources":["../../../src/figma/Alert.Description.figma.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,OAAO,CAAC;;;;;;AAM1B,wBAIE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Alert.Title.figma.d.ts","sourceRoot":"","sources":["../../../src/figma/Alert.Title.figma.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,OAAO,CAAC;;;;;;AAM1B,wBAIE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Alert.figma.d.ts","sourceRoot":"","sources":["../../../src/figma/Alert.figma.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,OAAO,CAAC;;;;;;AA4B1B,wBAiBE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QuickActionButton.figma.d.ts","sourceRoot":"","sources":["../../../src/figma/QuickActionButton.figma.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,OAAO,CAAC;;;;;;AAqB1B,wBAQE"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cdx-ui/components",
|
|
3
|
-
"version": "0.0.1-beta.
|
|
3
|
+
"version": "0.0.1-beta.72",
|
|
4
4
|
"main": "lib/commonjs/index.js",
|
|
5
5
|
"module": "lib/module/index.js",
|
|
6
6
|
"react-native": "src/index.ts",
|
|
@@ -67,9 +67,9 @@
|
|
|
67
67
|
"@gorhom/bottom-sheet": "^5.2.6",
|
|
68
68
|
"class-variance-authority": "^0.7.1",
|
|
69
69
|
"uniwind": "1.6.1",
|
|
70
|
-
"@cdx-ui/utils": "0.0.1-beta.
|
|
71
|
-
"@cdx-ui/
|
|
72
|
-
"@cdx-ui/
|
|
70
|
+
"@cdx-ui/utils": "0.0.1-beta.72",
|
|
71
|
+
"@cdx-ui/icons": "0.0.1-beta.72",
|
|
72
|
+
"@cdx-ui/primitives": "0.0.1-beta.72"
|
|
73
73
|
},
|
|
74
74
|
"devDependencies": {
|
|
75
75
|
"@react-navigation/bottom-tabs": "*",
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
import React, { forwardRef, useMemo, type ReactNode } from 'react';
|
|
2
|
+
import { Text, View, type TextProps, type ViewProps } from 'react-native';
|
|
3
|
+
import { Slot, dataAttributes, mergeDataAttributes } from '@cdx-ui/primitives';
|
|
4
|
+
import type { ForgeIcon } from '@cdx-ui/icons';
|
|
5
|
+
import { CheckCircle, EmergencyHome, Info, Warning } from '@cdx-ui/icons';
|
|
6
|
+
import { cn, ParentContext, useParentContext, useStyleContext } from '@cdx-ui/utils';
|
|
7
|
+
import { Icon, type IconProps } from '../Icon';
|
|
8
|
+
import {
|
|
9
|
+
alertActionsVariants,
|
|
10
|
+
alertBodyVariants,
|
|
11
|
+
alertDescriptionVariants,
|
|
12
|
+
alertIconVariants,
|
|
13
|
+
alertRootVariants,
|
|
14
|
+
alertTextVariants,
|
|
15
|
+
alertTitleVariants,
|
|
16
|
+
type AlertSeverity,
|
|
17
|
+
type AlertVariantProps,
|
|
18
|
+
} from './styles';
|
|
19
|
+
|
|
20
|
+
// =============================================================================
|
|
21
|
+
// CONTEXT
|
|
22
|
+
// =============================================================================
|
|
23
|
+
|
|
24
|
+
const SCOPE = 'ALERT';
|
|
25
|
+
|
|
26
|
+
interface AlertContextValue {
|
|
27
|
+
severity: AlertSeverity;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const useAlertStyleContext = (): AlertContextValue => {
|
|
31
|
+
const ctx = useStyleContext(SCOPE) as { severity?: AlertSeverity };
|
|
32
|
+
return { severity: ctx?.severity ?? 'info' };
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// Severity → default icon mapping
|
|
36
|
+
const SEVERITY_ICONS: Record<AlertSeverity, ForgeIcon> = {
|
|
37
|
+
danger: EmergencyHome,
|
|
38
|
+
warning: Warning,
|
|
39
|
+
success: CheckCircle,
|
|
40
|
+
info: Info,
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// =============================================================================
|
|
44
|
+
// ROOT
|
|
45
|
+
// =============================================================================
|
|
46
|
+
|
|
47
|
+
export interface AlertProps extends ViewProps, AlertVariantProps {
|
|
48
|
+
/**
|
|
49
|
+
* Replace the root element with the consumer's child element via `Slot`.
|
|
50
|
+
* When `true`, children are rendered as-is (no automatic icon/text/actions
|
|
51
|
+
* layout splitting). Severity context is still provided so sub-components
|
|
52
|
+
* receive the correct styles.
|
|
53
|
+
*/
|
|
54
|
+
asChild?: boolean;
|
|
55
|
+
/** Severity level that controls background colour, icon, and live-region urgency. */
|
|
56
|
+
severity?: AlertSeverity;
|
|
57
|
+
className?: string;
|
|
58
|
+
/**
|
|
59
|
+
* Sub-components (`Alert.Icon`, `Alert.Title`, `Alert.Description`,
|
|
60
|
+
* `Alert.Actions`) must be rendered as **direct** children — wrapping them
|
|
61
|
+
* in HOCs or `memo()` will break the automatic layout splitting.
|
|
62
|
+
*/
|
|
63
|
+
children?: ReactNode;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const AlertRoot = forwardRef<View, AlertProps>(
|
|
67
|
+
({ asChild, severity = 'info', className, style, children, ...props }, ref) => {
|
|
68
|
+
const isAssertive = severity === 'danger' || severity === 'warning';
|
|
69
|
+
const parent = useParentContext();
|
|
70
|
+
const ctx = useMemo(() => ({ ...parent, [SCOPE]: { severity } }), [parent, severity]);
|
|
71
|
+
|
|
72
|
+
const rootClassName = cn(alertRootVariants({ severity }), className);
|
|
73
|
+
const role = isAssertive ? 'alert' : 'status';
|
|
74
|
+
const liveRegion = isAssertive ? 'assertive' : 'polite';
|
|
75
|
+
const dataProps = mergeDataAttributes(props, dataAttributes({ slot: 'alert' }));
|
|
76
|
+
|
|
77
|
+
if (asChild) {
|
|
78
|
+
return (
|
|
79
|
+
<ParentContext.Provider value={ctx}>
|
|
80
|
+
<Slot
|
|
81
|
+
ref={ref}
|
|
82
|
+
className={rootClassName}
|
|
83
|
+
style={style}
|
|
84
|
+
role={role}
|
|
85
|
+
accessibilityLiveRegion={liveRegion}
|
|
86
|
+
{...props}
|
|
87
|
+
{...dataProps}
|
|
88
|
+
>
|
|
89
|
+
{children}
|
|
90
|
+
</Slot>
|
|
91
|
+
</ParentContext.Provider>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Split children into three regions:
|
|
96
|
+
// 1. Alert.Icon — rendered at inline-start (left)
|
|
97
|
+
// 2. Alert.Actions — rendered at inline-end (right), beside the text
|
|
98
|
+
// 3. Everything else (Title, Description) — text column, flex-1
|
|
99
|
+
//
|
|
100
|
+
// Layout: [Icon] [flex-1 flex-row: [text flex-1] [Actions]]
|
|
101
|
+
const childArray = React.Children.toArray(children);
|
|
102
|
+
const iconChild = childArray.find(
|
|
103
|
+
(child) =>
|
|
104
|
+
React.isValidElement(child) && (child as React.ReactElement).type === AlertIconComponent,
|
|
105
|
+
);
|
|
106
|
+
const actionsChild = childArray.find(
|
|
107
|
+
(child) => React.isValidElement(child) && (child as React.ReactElement).type === AlertActions,
|
|
108
|
+
);
|
|
109
|
+
const textChildren = childArray.filter(
|
|
110
|
+
(child) =>
|
|
111
|
+
!React.isValidElement(child) ||
|
|
112
|
+
((child as React.ReactElement).type !== AlertIconComponent &&
|
|
113
|
+
(child as React.ReactElement).type !== AlertActions),
|
|
114
|
+
);
|
|
115
|
+
const hasBody = textChildren.length > 0 || !!actionsChild;
|
|
116
|
+
|
|
117
|
+
return (
|
|
118
|
+
<ParentContext.Provider value={ctx}>
|
|
119
|
+
<View
|
|
120
|
+
ref={ref}
|
|
121
|
+
className={rootClassName}
|
|
122
|
+
style={style}
|
|
123
|
+
role={role}
|
|
124
|
+
accessibilityLiveRegion={liveRegion}
|
|
125
|
+
{...props}
|
|
126
|
+
{...dataProps}
|
|
127
|
+
>
|
|
128
|
+
{iconChild}
|
|
129
|
+
{hasBody ? (
|
|
130
|
+
<View className={alertBodyVariants()}>
|
|
131
|
+
{textChildren.length > 0 ? (
|
|
132
|
+
<View className={alertTextVariants()}>{textChildren}</View>
|
|
133
|
+
) : null}
|
|
134
|
+
{actionsChild}
|
|
135
|
+
</View>
|
|
136
|
+
) : null}
|
|
137
|
+
</View>
|
|
138
|
+
</ParentContext.Provider>
|
|
139
|
+
);
|
|
140
|
+
},
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
AlertRoot.displayName = 'Alert';
|
|
144
|
+
|
|
145
|
+
// =============================================================================
|
|
146
|
+
// ICON
|
|
147
|
+
// =============================================================================
|
|
148
|
+
|
|
149
|
+
export interface AlertIconProps extends Omit<IconProps, 'as'> {
|
|
150
|
+
asChild?: boolean;
|
|
151
|
+
/**
|
|
152
|
+
* Override the auto-rendered severity icon. Omit to use the default icon for
|
|
153
|
+
* the current severity (EmergencyHome, Warning, CheckCircle, or Info).
|
|
154
|
+
* Not required when `asChild` is set.
|
|
155
|
+
*/
|
|
156
|
+
as?: ForgeIcon;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const AlertIconComponent = forwardRef<View, AlertIconProps>(
|
|
160
|
+
({ asChild, as: asOverride, className, style, ...props }, ref) => {
|
|
161
|
+
const { severity } = useAlertStyleContext();
|
|
162
|
+
const computedClassName = cn(alertIconVariants({ severity }), className);
|
|
163
|
+
|
|
164
|
+
if (asChild) {
|
|
165
|
+
return (
|
|
166
|
+
<Slot
|
|
167
|
+
ref={ref}
|
|
168
|
+
className={computedClassName}
|
|
169
|
+
style={style}
|
|
170
|
+
{...props}
|
|
171
|
+
{...mergeDataAttributes(props, dataAttributes({ slot: 'alert-icon' }))}
|
|
172
|
+
/>
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return (
|
|
177
|
+
<Icon
|
|
178
|
+
as={asOverride ?? SEVERITY_ICONS[severity]}
|
|
179
|
+
className={computedClassName}
|
|
180
|
+
style={style}
|
|
181
|
+
{...props}
|
|
182
|
+
{...mergeDataAttributes(props, dataAttributes({ slot: 'alert-icon' }))}
|
|
183
|
+
/>
|
|
184
|
+
);
|
|
185
|
+
},
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
AlertIconComponent.displayName = 'Alert.Icon';
|
|
189
|
+
|
|
190
|
+
// =============================================================================
|
|
191
|
+
// TITLE
|
|
192
|
+
// =============================================================================
|
|
193
|
+
|
|
194
|
+
export interface AlertTitleProps extends TextProps {
|
|
195
|
+
asChild?: boolean;
|
|
196
|
+
className?: string;
|
|
197
|
+
children?: ReactNode;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const AlertTitle = forwardRef<Text, AlertTitleProps>(
|
|
201
|
+
({ asChild, className, style, children, ...props }, ref) => {
|
|
202
|
+
const { severity } = useAlertStyleContext();
|
|
203
|
+
const computedClassName = cn(alertTitleVariants({ severity }), className);
|
|
204
|
+
const Comp = asChild ? Slot : Text;
|
|
205
|
+
|
|
206
|
+
return (
|
|
207
|
+
<Comp
|
|
208
|
+
ref={ref}
|
|
209
|
+
className={computedClassName}
|
|
210
|
+
style={style}
|
|
211
|
+
{...props}
|
|
212
|
+
{...mergeDataAttributes(props, dataAttributes({ slot: 'alert-title' }))}
|
|
213
|
+
>
|
|
214
|
+
{children}
|
|
215
|
+
</Comp>
|
|
216
|
+
);
|
|
217
|
+
},
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
AlertTitle.displayName = 'Alert.Title';
|
|
221
|
+
|
|
222
|
+
// =============================================================================
|
|
223
|
+
// DESCRIPTION
|
|
224
|
+
// =============================================================================
|
|
225
|
+
|
|
226
|
+
export interface AlertDescriptionProps extends TextProps {
|
|
227
|
+
asChild?: boolean;
|
|
228
|
+
className?: string;
|
|
229
|
+
children?: ReactNode;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const AlertDescription = forwardRef<Text, AlertDescriptionProps>(
|
|
233
|
+
({ asChild, className, style, children, ...props }, ref) => {
|
|
234
|
+
const { severity } = useAlertStyleContext();
|
|
235
|
+
const computedClassName = cn(alertDescriptionVariants({ severity }), className);
|
|
236
|
+
const Comp = asChild ? Slot : Text;
|
|
237
|
+
|
|
238
|
+
return (
|
|
239
|
+
<Comp
|
|
240
|
+
ref={ref}
|
|
241
|
+
className={computedClassName}
|
|
242
|
+
style={style}
|
|
243
|
+
{...props}
|
|
244
|
+
{...mergeDataAttributes(props, dataAttributes({ slot: 'alert-description' }))}
|
|
245
|
+
>
|
|
246
|
+
{children}
|
|
247
|
+
</Comp>
|
|
248
|
+
);
|
|
249
|
+
},
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
AlertDescription.displayName = 'Alert.Description';
|
|
253
|
+
|
|
254
|
+
// =============================================================================
|
|
255
|
+
// ACTIONS
|
|
256
|
+
// =============================================================================
|
|
257
|
+
|
|
258
|
+
export interface AlertActionsProps extends ViewProps {
|
|
259
|
+
/**
|
|
260
|
+
* Replace the wrapper element with the consumer's child via `Slot`.
|
|
261
|
+
* **Note:** when `true`, automatic `color={severity}` injection on
|
|
262
|
+
* direct `Button`/`IconButton` children is bypassed — the consumer
|
|
263
|
+
* must set `color` explicitly.
|
|
264
|
+
*/
|
|
265
|
+
asChild?: boolean;
|
|
266
|
+
className?: string;
|
|
267
|
+
children?: ReactNode;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const AlertActions = forwardRef<View, AlertActionsProps>(
|
|
271
|
+
({ asChild, className, style, children, ...props }, ref) => {
|
|
272
|
+
const { severity } = useAlertStyleContext();
|
|
273
|
+
const computedClassName = cn(alertActionsVariants(), className);
|
|
274
|
+
const Comp = asChild ? Slot : View;
|
|
275
|
+
|
|
276
|
+
// Auto-inject color={severity} on direct Button / IconButton children unless
|
|
277
|
+
// the consumer already provides a color prop.
|
|
278
|
+
const injectedChildren = React.Children.map(children, (child) => {
|
|
279
|
+
if (!React.isValidElement<{ color?: unknown }>(child)) return child;
|
|
280
|
+
if ('color' in child.props) return child;
|
|
281
|
+
return React.cloneElement(child, { color: severity });
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
return (
|
|
285
|
+
<Comp
|
|
286
|
+
ref={ref}
|
|
287
|
+
className={computedClassName}
|
|
288
|
+
style={style}
|
|
289
|
+
{...props}
|
|
290
|
+
{...mergeDataAttributes(props, dataAttributes({ slot: 'alert-actions' }))}
|
|
291
|
+
>
|
|
292
|
+
{asChild ? children : injectedChildren}
|
|
293
|
+
</Comp>
|
|
294
|
+
);
|
|
295
|
+
},
|
|
296
|
+
);
|
|
297
|
+
|
|
298
|
+
AlertActions.displayName = 'Alert.Actions';
|
|
299
|
+
|
|
300
|
+
// =============================================================================
|
|
301
|
+
// COMPOUND EXPORT
|
|
302
|
+
// =============================================================================
|
|
303
|
+
|
|
304
|
+
type AlertCompoundComponent = typeof AlertRoot & {
|
|
305
|
+
Icon: typeof AlertIconComponent;
|
|
306
|
+
Title: typeof AlertTitle;
|
|
307
|
+
Description: typeof AlertDescription;
|
|
308
|
+
Actions: typeof AlertActions;
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
export const Alert = Object.assign(AlertRoot, {
|
|
312
|
+
Icon: AlertIconComponent,
|
|
313
|
+
Title: AlertTitle,
|
|
314
|
+
Description: AlertDescription,
|
|
315
|
+
Actions: AlertActions,
|
|
316
|
+
}) as AlertCompoundComponent;
|
|
317
|
+
|
|
318
|
+
export type { AlertVariantProps, AlertSeverity };
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { cva, type VariantProps } from 'class-variance-authority';
|
|
2
|
+
|
|
3
|
+
// ── Severity type ────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
export type AlertSeverity = 'danger' | 'warning' | 'success' | 'info';
|
|
6
|
+
|
|
7
|
+
// ── Root ─────────────────────────────────────────────────────────────────────
|
|
8
|
+
|
|
9
|
+
export const alertRootVariants = cva(
|
|
10
|
+
['flex-row items-start', 'gap-2 px-3', 'rounded-[var(--border-radius-default)]'],
|
|
11
|
+
{
|
|
12
|
+
variants: {
|
|
13
|
+
severity: {
|
|
14
|
+
danger: 'bg-surface-danger-subtle',
|
|
15
|
+
warning: 'bg-surface-warning-subtle',
|
|
16
|
+
success: 'bg-surface-success-subtle',
|
|
17
|
+
info: 'bg-surface-info-subtle',
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
defaultVariants: {
|
|
21
|
+
severity: 'info',
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
// ── Icon ─────────────────────────────────────────────────────────────────────
|
|
27
|
+
|
|
28
|
+
export const alertIconVariants = cva(['size-5 shrink-0 mt-3'], {
|
|
29
|
+
variants: {
|
|
30
|
+
severity: {
|
|
31
|
+
danger: 'text-content-danger-on-subtle',
|
|
32
|
+
warning: 'text-content-warning-on-subtle',
|
|
33
|
+
success: 'text-content-success-on-subtle',
|
|
34
|
+
info: 'text-content-info-on-subtle',
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
defaultVariants: {
|
|
38
|
+
severity: 'info',
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// ── Body (internal row: text area + trailing actions) ────────────────────────
|
|
43
|
+
|
|
44
|
+
export const alertBodyVariants = cva(['flex-1 flex-row items-start gap-2 min-w-0']);
|
|
45
|
+
|
|
46
|
+
// ── Text (internal flex-col for title + description) ─────────────────────────
|
|
47
|
+
|
|
48
|
+
export const alertTextVariants = cva(['flex-1 flex-col gap-1 min-w-0 mt-3 mb-3']);
|
|
49
|
+
|
|
50
|
+
// ── Title ────────────────────────────────────────────────────────────────────
|
|
51
|
+
|
|
52
|
+
export const alertTitleVariants = cva(['body-md font-semibold'], {
|
|
53
|
+
variants: {
|
|
54
|
+
severity: {
|
|
55
|
+
danger: 'text-content-danger-on-subtle',
|
|
56
|
+
warning: 'text-content-warning-on-subtle',
|
|
57
|
+
success: 'text-content-success-on-subtle',
|
|
58
|
+
info: 'text-content-info-on-subtle',
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
defaultVariants: {
|
|
62
|
+
severity: 'info',
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// ── Description ──────────────────────────────────────────────────────────────
|
|
67
|
+
|
|
68
|
+
export const alertDescriptionVariants = cva(['body-md'], {
|
|
69
|
+
variants: {
|
|
70
|
+
severity: {
|
|
71
|
+
danger: 'text-content-danger-on-subtle',
|
|
72
|
+
warning: 'text-content-warning-on-subtle',
|
|
73
|
+
success: 'text-content-success-on-subtle',
|
|
74
|
+
info: 'text-content-info-on-subtle',
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
defaultVariants: {
|
|
78
|
+
severity: 'info',
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// ── Actions ──────────────────────────────────────────────────────────────────
|
|
83
|
+
|
|
84
|
+
export const alertActionsVariants = cva(['shrink-0 flex-row items-center gap-1.5 mt-1.5 mb-1.5']);
|
|
85
|
+
|
|
86
|
+
// ── Types ─────────────────────────────────────────────────────────────────────
|
|
87
|
+
|
|
88
|
+
export type AlertVariantProps = VariantProps<typeof alertRootVariants>;
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { forwardRef, type ReactNode } from 'react';
|
|
2
|
+
import { Text, View, type PressableProps, type TextProps, type ViewProps } from 'react-native';
|
|
3
|
+
import {
|
|
4
|
+
ButtonRoot,
|
|
5
|
+
dataAttributes,
|
|
6
|
+
mergeDataAttributes,
|
|
7
|
+
type IButtonProps,
|
|
8
|
+
useButtonContext,
|
|
9
|
+
} from '@cdx-ui/primitives';
|
|
10
|
+
import type { ForgeIcon } from '@cdx-ui/icons';
|
|
11
|
+
import { cn } from '@cdx-ui/utils';
|
|
12
|
+
import { Icon, type IconProps } from '../Icon';
|
|
13
|
+
import {
|
|
14
|
+
quickActionButtonGlyphVariants,
|
|
15
|
+
quickActionButtonIndicatorVariants,
|
|
16
|
+
quickActionButtonLabelVariants,
|
|
17
|
+
quickActionButtonRootVariants,
|
|
18
|
+
type QuickActionButtonVariantProps,
|
|
19
|
+
} from './styles';
|
|
20
|
+
|
|
21
|
+
// =============================================================================
|
|
22
|
+
// ROOT
|
|
23
|
+
// =============================================================================
|
|
24
|
+
|
|
25
|
+
export interface QuickActionButtonProps extends PressableProps, IButtonProps {
|
|
26
|
+
className?: string;
|
|
27
|
+
children?: ReactNode;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const QuickActionButtonRoot = forwardRef<View, QuickActionButtonProps>(
|
|
31
|
+
({ className, style, children, accessibilityRole = 'button', ...props }, ref) => (
|
|
32
|
+
<ButtonRoot
|
|
33
|
+
ref={ref}
|
|
34
|
+
accessibilityRole={accessibilityRole}
|
|
35
|
+
className={cn(quickActionButtonRootVariants(), className)}
|
|
36
|
+
style={style}
|
|
37
|
+
{...props}
|
|
38
|
+
{...mergeDataAttributes(props, dataAttributes({ slot: 'quick-action-button' }))}
|
|
39
|
+
>
|
|
40
|
+
{children}
|
|
41
|
+
</ButtonRoot>
|
|
42
|
+
),
|
|
43
|
+
);
|
|
44
|
+
QuickActionButtonRoot.displayName = 'QuickActionButton';
|
|
45
|
+
|
|
46
|
+
// =============================================================================
|
|
47
|
+
// INDICATOR
|
|
48
|
+
// Circular container. Auto-rendered by `QuickActionButton.Icon` in standard usage.
|
|
49
|
+
// Exposed as a compound member for Code Connect parity and custom compositions.
|
|
50
|
+
// =============================================================================
|
|
51
|
+
|
|
52
|
+
export interface QuickActionButtonIndicatorProps extends ViewProps {
|
|
53
|
+
className?: string;
|
|
54
|
+
children?: ReactNode;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const QuickActionButtonIndicator = forwardRef<View, QuickActionButtonIndicatorProps>(
|
|
58
|
+
({ className, style, children, ...props }, ref) => {
|
|
59
|
+
const { hover, focus, active, disabled, focusVisible } = useButtonContext();
|
|
60
|
+
return (
|
|
61
|
+
<View
|
|
62
|
+
ref={ref}
|
|
63
|
+
className={cn(quickActionButtonIndicatorVariants(), className)}
|
|
64
|
+
style={style}
|
|
65
|
+
{...props}
|
|
66
|
+
{...mergeDataAttributes(
|
|
67
|
+
props,
|
|
68
|
+
dataAttributes({
|
|
69
|
+
slot: 'quick-action-button-indicator',
|
|
70
|
+
hover,
|
|
71
|
+
focus,
|
|
72
|
+
active,
|
|
73
|
+
disabled,
|
|
74
|
+
focusVisible,
|
|
75
|
+
}),
|
|
76
|
+
)}
|
|
77
|
+
>
|
|
78
|
+
{children}
|
|
79
|
+
</View>
|
|
80
|
+
);
|
|
81
|
+
},
|
|
82
|
+
);
|
|
83
|
+
QuickActionButtonIndicator.displayName = 'QuickActionButton.Indicator';
|
|
84
|
+
|
|
85
|
+
// =============================================================================
|
|
86
|
+
// ICON
|
|
87
|
+
// Renders the Indicator circle + icon glyph as one convenient sub-component.
|
|
88
|
+
// This is the primary way consumers add the icon to a QuickActionButton.
|
|
89
|
+
// =============================================================================
|
|
90
|
+
|
|
91
|
+
export interface QuickActionButtonIconProps {
|
|
92
|
+
/** Forge icon component to render inside the circular indicator. */
|
|
93
|
+
as: ForgeIcon;
|
|
94
|
+
/** Applied to the icon glyph, not the indicator circle. */
|
|
95
|
+
className?: IconProps['className'];
|
|
96
|
+
/** Applied to the indicator circle wrapper. */
|
|
97
|
+
indicatorClassName?: string;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function QuickActionButtonIcon({
|
|
101
|
+
as: IconComponent,
|
|
102
|
+
className,
|
|
103
|
+
indicatorClassName,
|
|
104
|
+
}: QuickActionButtonIconProps) {
|
|
105
|
+
return (
|
|
106
|
+
<QuickActionButtonIndicator className={indicatorClassName}>
|
|
107
|
+
<Icon as={IconComponent} className={cn(quickActionButtonGlyphVariants(), className)} />
|
|
108
|
+
</QuickActionButtonIndicator>
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
QuickActionButtonIcon.displayName = 'QuickActionButton.Icon';
|
|
112
|
+
|
|
113
|
+
// =============================================================================
|
|
114
|
+
// LABEL
|
|
115
|
+
// =============================================================================
|
|
116
|
+
|
|
117
|
+
export interface QuickActionButtonLabelProps extends TextProps {
|
|
118
|
+
className?: string;
|
|
119
|
+
children?: ReactNode;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const QuickActionButtonLabel = forwardRef<Text, QuickActionButtonLabelProps>(
|
|
123
|
+
({ className, style, children, ...props }, ref) => {
|
|
124
|
+
const { disabled } = useButtonContext();
|
|
125
|
+
return (
|
|
126
|
+
<Text
|
|
127
|
+
ref={ref}
|
|
128
|
+
numberOfLines={2}
|
|
129
|
+
ellipsizeMode="tail"
|
|
130
|
+
className={cn(quickActionButtonLabelVariants(), className)}
|
|
131
|
+
style={style}
|
|
132
|
+
{...props}
|
|
133
|
+
{...mergeDataAttributes(
|
|
134
|
+
props,
|
|
135
|
+
dataAttributes({ slot: 'quick-action-button-label', disabled }),
|
|
136
|
+
)}
|
|
137
|
+
>
|
|
138
|
+
{children}
|
|
139
|
+
</Text>
|
|
140
|
+
);
|
|
141
|
+
},
|
|
142
|
+
);
|
|
143
|
+
QuickActionButtonLabel.displayName = 'QuickActionButton.Label';
|
|
144
|
+
|
|
145
|
+
// =============================================================================
|
|
146
|
+
// COMPOUND EXPORT
|
|
147
|
+
// =============================================================================
|
|
148
|
+
|
|
149
|
+
type QuickActionButtonCompoundComponent = typeof QuickActionButtonRoot & {
|
|
150
|
+
Indicator: typeof QuickActionButtonIndicator;
|
|
151
|
+
Icon: typeof QuickActionButtonIcon;
|
|
152
|
+
Label: typeof QuickActionButtonLabel;
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
export const QuickActionButton = Object.assign(QuickActionButtonRoot, {
|
|
156
|
+
Indicator: QuickActionButtonIndicator,
|
|
157
|
+
Icon: QuickActionButtonIcon,
|
|
158
|
+
Label: QuickActionButtonLabel,
|
|
159
|
+
}) as QuickActionButtonCompoundComponent;
|
|
160
|
+
|
|
161
|
+
export type { QuickActionButtonVariantProps };
|