@butternutbox/pawprint-native 0.0.1 → 0.1.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.
- package/.turbo/turbo-build.log +15 -15
- package/CHANGELOG.md +16 -0
- package/COMPONENT_GUIDELINES.md +111 -4
- package/dist/index.cjs +12370 -1455
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1110 -11
- package/dist/index.d.ts +1110 -11
- package/dist/index.js +12324 -1455
- package/dist/index.js.map +1 -1
- package/package.json +28 -9
- package/src/__mocks__/asset-stub.ts +1 -0
- package/src/__mocks__/emotion-native.tsx +18 -0
- package/src/__mocks__/react-native-gesture-handler.tsx +41 -0
- package/src/__mocks__/react-native-reanimated.tsx +79 -0
- package/src/__mocks__/react-native-safe-area-context.tsx +6 -0
- package/src/__mocks__/react-native-svg.tsx +27 -0
- package/src/__mocks__/react-native-worklets.tsx +11 -0
- package/src/__mocks__/react-native.tsx +338 -0
- package/src/__mocks__/rn-primitives/avatar.tsx +24 -0
- package/src/__mocks__/rn-primitives/checkbox.tsx +19 -0
- package/src/__mocks__/rn-primitives/select.tsx +116 -0
- package/src/__mocks__/rn-primitives/slider.tsx +40 -0
- package/src/__mocks__/rn-primitives/slot.tsx +30 -0
- package/src/__mocks__/rn-primitives/switch.tsx +24 -0
- package/src/__mocks__/rn-primitives/toggle.tsx +16 -0
- package/src/components/atoms/Avatar/Avatar.stories.tsx +57 -49
- package/src/components/atoms/Avatar/Avatar.test.tsx +269 -0
- package/src/components/atoms/Avatar/Avatar.tsx +68 -22
- package/src/components/atoms/Avatar/index.ts +1 -6
- package/src/components/atoms/Badge/Badge.stories.tsx +5 -29
- package/src/components/atoms/Badge/Badge.test.tsx +90 -0
- package/src/components/atoms/Button/Button.test.tsx +123 -0
- package/src/components/atoms/Button/Button.tsx +1 -1
- package/src/components/atoms/CarouselControls/CarouselControls.stories.tsx +217 -0
- package/src/components/atoms/CarouselControls/CarouselControls.tsx +127 -0
- package/src/components/atoms/CarouselControls/index.ts +2 -0
- package/src/components/atoms/Hint/Hint.test.tsx +36 -0
- package/src/components/atoms/Icon/Icon.test.tsx +98 -0
- package/src/components/atoms/Icon/Icon.tsx +5 -1
- package/src/components/atoms/IconButton/IconButton.test.tsx +101 -0
- package/src/components/atoms/Illustration/Illustration.test.tsx +55 -0
- package/src/components/atoms/Input/Input.stories.tsx +129 -86
- package/src/components/atoms/Input/Input.test.tsx +306 -0
- package/src/components/atoms/Input/Input.tsx +9 -1
- package/src/components/atoms/Input/InputField.tsx +226 -74
- package/src/components/atoms/Link/Link.test.tsx +89 -0
- package/src/components/atoms/Logo/Logo.registry.ts +30 -5
- package/src/components/atoms/Logo/Logo.stories.tsx +108 -0
- package/src/components/atoms/Logo/Logo.test.tsx +56 -0
- package/src/components/atoms/Logo/assets/BCorp.tsx +113 -0
- package/src/components/atoms/Logo/assets/ButternutFavicon.tsx +33 -0
- package/src/components/atoms/Logo/assets/ButternutPrimary.tsx +294 -0
- package/src/components/atoms/Logo/assets/ButternutTabbedBottom.tsx +294 -0
- package/src/components/atoms/Logo/assets/ButternutTabbedTop.tsx +294 -0
- package/src/components/atoms/Logo/assets/ButternutWordmark.tsx +274 -0
- package/src/components/atoms/Logo/assets/PsiBufetFavicon.tsx +45 -0
- package/src/components/atoms/Logo/assets/PsiBufetPrimary.tsx +218 -0
- package/src/components/atoms/Logo/assets/PsiBufetTabbedBottom.tsx +218 -0
- package/src/components/atoms/Logo/assets/PsiBufetTabbedTop.tsx +218 -0
- package/src/components/atoms/Logo/assets/PsiBufetWordmark.tsx +195 -0
- package/src/components/atoms/Logo/assets/index.ts +11 -0
- package/src/components/atoms/NumberInput/NumberInput.stories.tsx +183 -0
- package/src/components/atoms/NumberInput/NumberInput.test.tsx +261 -0
- package/src/components/atoms/NumberInput/NumberInput.tsx +129 -0
- package/src/components/atoms/NumberInput/NumberInputField.tsx +77 -0
- package/src/components/atoms/NumberInput/index.ts +4 -0
- package/src/components/atoms/Spinner/Spinner.test.tsx +46 -0
- package/src/components/atoms/Spinner/Spinner.tsx +14 -5
- package/src/components/atoms/Switch/Switch.test.tsx +92 -0
- package/src/components/atoms/Switch/Switch.tsx +16 -13
- package/src/components/atoms/Tag/Tag.test.tsx +70 -0
- package/src/components/atoms/TextArea/TextArea.stories.tsx +303 -0
- package/src/components/atoms/TextArea/TextArea.test.tsx +416 -0
- package/src/components/atoms/TextArea/TextArea.tsx +171 -0
- package/src/components/atoms/TextArea/TextAreaField.tsx +304 -0
- package/src/components/atoms/TextArea/TextAreaLabel.tsx +103 -0
- package/src/components/atoms/TextArea/index.ts +6 -0
- package/src/components/atoms/Typography/Typography.test.tsx +94 -0
- package/src/components/atoms/index.ts +3 -0
- package/src/components/molecules/Accordion/Accordion.stories.tsx +177 -0
- package/src/components/molecules/Accordion/Accordion.test.tsx +185 -0
- package/src/components/molecules/Accordion/Accordion.tsx +284 -0
- package/src/components/molecules/Accordion/index.ts +6 -0
- package/src/components/molecules/Animated/Animated.stories.tsx +254 -0
- package/src/components/molecules/Animated/Animated.tsx +283 -0
- package/src/components/molecules/Animated/index.ts +10 -0
- package/src/components/molecules/ButtonDock/ButtonDock.test.tsx +83 -0
- package/src/components/molecules/ButtonGroup/ButtonGroup.stories.tsx +8 -14
- package/src/components/molecules/ButtonGroup/ButtonGroup.test.tsx +73 -0
- package/src/components/molecules/ButtonGroup/ButtonGroup.tsx +25 -3
- package/src/components/molecules/Checkbox/Checkbox.stories.tsx +72 -0
- package/src/components/molecules/Checkbox/Checkbox.test.tsx +117 -0
- package/src/components/molecules/Checkbox/Checkbox.tsx +101 -95
- package/src/components/molecules/CopyField/CopyField.stories.tsx +313 -0
- package/src/components/molecules/CopyField/CopyField.test.tsx +431 -0
- package/src/components/molecules/CopyField/CopyField.tsx +156 -0
- package/src/components/molecules/CopyField/CopyFieldInput.tsx +127 -0
- package/src/components/molecules/CopyField/hooks/index.ts +1 -0
- package/src/components/molecules/CopyField/hooks/useCopyField.ts +25 -0
- package/src/components/molecules/CopyField/index.ts +4 -0
- package/src/components/molecules/DatePicker/DatePicker.stories.tsx +298 -0
- package/src/components/molecules/DatePicker/DatePicker.test.tsx +201 -0
- package/src/components/molecules/DatePicker/DatePicker.tsx +590 -0
- package/src/components/molecules/DatePicker/index.ts +2 -0
- package/src/components/molecules/Drawer/Drawer.stories.tsx +285 -0
- package/src/components/molecules/Drawer/Drawer.test.tsx +180 -0
- package/src/components/molecules/Drawer/Drawer.tsx +187 -0
- package/src/components/molecules/Drawer/DrawerBody.tsx +80 -0
- package/src/components/molecules/Drawer/DrawerClose.tsx +76 -0
- package/src/components/molecules/Drawer/DrawerContent.tsx +339 -0
- package/src/components/molecules/Drawer/DrawerContext.ts +19 -0
- package/src/components/molecules/Drawer/DrawerDescription.tsx +31 -0
- package/src/components/molecules/Drawer/DrawerDragContext.ts +11 -0
- package/src/components/molecules/Drawer/DrawerFooter.tsx +49 -0
- package/src/components/molecules/Drawer/DrawerFooterContext.ts +6 -0
- package/src/components/molecules/Drawer/DrawerGrabber.tsx +62 -0
- package/src/components/molecules/Drawer/DrawerHeader.tsx +244 -0
- package/src/components/molecules/Drawer/DrawerHeaderContext.ts +13 -0
- package/src/components/molecules/Drawer/DrawerOverlay.tsx +53 -0
- package/src/components/molecules/Drawer/DrawerTitle.tsx +32 -0
- package/src/components/molecules/Drawer/index.ts +12 -0
- package/src/components/molecules/FilterTab/FilterTab.stories.tsx +210 -0
- package/src/components/molecules/FilterTab/FilterTab.tsx +310 -0
- package/src/components/molecules/FilterTab/index.ts +2 -0
- package/src/components/molecules/MessageCard/MessageCard.stories.tsx +169 -0
- package/src/components/molecules/MessageCard/MessageCard.tsx +362 -0
- package/src/components/molecules/MessageCard/index.ts +10 -0
- package/src/components/molecules/Notification/Notification.stories.tsx +219 -0
- package/src/components/molecules/Notification/Notification.tsx +426 -0
- package/src/components/molecules/Notification/index.ts +2 -0
- package/src/components/molecules/NumberField/NumberField.stories.tsx +231 -0
- package/src/components/molecules/NumberField/NumberField.tsx +186 -0
- package/src/components/molecules/NumberField/NumberFieldInput.tsx +287 -0
- package/src/components/molecules/NumberField/index.ts +2 -0
- package/src/components/molecules/PasswordField/PasswordField.stories.tsx +362 -0
- package/src/components/molecules/PasswordField/PasswordField.test.tsx +369 -0
- package/src/components/molecules/PasswordField/PasswordField.tsx +194 -0
- package/src/components/molecules/PasswordField/PasswordFieldError.tsx +52 -0
- package/src/components/molecules/PasswordField/PasswordFieldInput.tsx +73 -0
- package/src/components/molecules/PasswordField/PasswordFieldRequirements.tsx +92 -0
- package/src/components/molecules/PasswordField/hooks/index.ts +2 -0
- package/src/components/molecules/PasswordField/hooks/usePasswordField.ts +113 -0
- package/src/components/molecules/PasswordField/index.ts +10 -0
- package/src/components/molecules/PictureSelector/PictureSelector.stories.tsx +243 -0
- package/src/components/molecules/PictureSelector/PictureSelector.tsx +313 -0
- package/src/components/molecules/PictureSelector/index.ts +5 -0
- package/src/components/molecules/Progress/Progress.stories.tsx +145 -0
- package/src/components/molecules/Progress/Progress.tsx +184 -0
- package/src/components/molecules/Progress/index.ts +2 -0
- package/src/components/molecules/Radio/Radio.test.tsx +104 -0
- package/src/components/molecules/Radio/Radio.tsx +1 -2
- package/src/components/molecules/SearchField/SearchField.stories.tsx +242 -0
- package/src/components/molecules/SearchField/SearchField.test.tsx +318 -0
- package/src/components/molecules/SearchField/SearchField.tsx +143 -0
- package/src/components/molecules/SearchField/SearchFieldInput.tsx +63 -0
- package/src/components/molecules/SearchField/hooks/index.ts +1 -0
- package/src/components/molecules/SearchField/hooks/useSearchField.ts +56 -0
- package/src/components/molecules/SearchField/index.ts +4 -0
- package/src/components/molecules/SegmentedControl/SegmentedControl.stories.tsx +31 -8
- package/src/components/molecules/SegmentedControl/SegmentedControl.test.tsx +141 -0
- package/src/components/molecules/SegmentedControl/SegmentedControl.tsx +237 -23
- package/src/components/molecules/SelectField/SelectField.stories.tsx +320 -0
- package/src/components/molecules/SelectField/SelectField.test.tsx +254 -0
- package/src/components/molecules/SelectField/SelectField.tsx +236 -0
- package/src/components/molecules/SelectField/SelectFieldContent.tsx +85 -0
- package/src/components/molecules/SelectField/SelectFieldItem.tsx +133 -0
- package/src/components/molecules/SelectField/SelectFieldTrigger.tsx +170 -0
- package/src/components/molecules/SelectField/SelectFieldValue.tsx +31 -0
- package/src/components/molecules/SelectField/hooks/index.ts +2 -0
- package/src/components/molecules/SelectField/hooks/useSelectField.ts +84 -0
- package/src/components/molecules/SelectField/index.ts +10 -0
- package/src/components/molecules/Slider/Slider.test.tsx +102 -0
- package/src/components/molecules/Slider/Slider.tsx +293 -180
- package/src/components/molecules/Tooltip/Tooltip.stories.tsx +168 -0
- package/src/components/molecules/Tooltip/Tooltip.tsx +326 -0
- package/src/components/molecules/Tooltip/index.ts +2 -0
- package/src/components/molecules/index.ts +15 -0
- package/src/test-utils.tsx +20 -0
- package/tsconfig.json +1 -1
- package/tsup.config.ts +16 -2
- package/vitest.config.ts +114 -0
- package/vitest.setup.ts +16 -0
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
import React, { useState } from "react"
|
|
2
|
+
import { View, StyleSheet } from "react-native"
|
|
3
|
+
import { CopyField } from "./CopyField"
|
|
4
|
+
import { Typography } from "../../atoms/Typography"
|
|
5
|
+
import { useCopyField } from "./hooks/useCopyField"
|
|
6
|
+
import type { InputState } from "../../atoms/Input/InputField"
|
|
7
|
+
import { Icon } from "../../atoms/Icon"
|
|
8
|
+
import { Lock } from "@butternutbox/pawprint-icons/core"
|
|
9
|
+
|
|
10
|
+
export default {
|
|
11
|
+
title: "Molecules/CopyField",
|
|
12
|
+
component: CopyField,
|
|
13
|
+
parameters: {
|
|
14
|
+
docs: {
|
|
15
|
+
description: {
|
|
16
|
+
component:
|
|
17
|
+
"Copy field component with a copy button that copies the input value to clipboard. Supports both simple props API and compound component API."
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
argTypes: {
|
|
22
|
+
label: {
|
|
23
|
+
control: { type: "text" },
|
|
24
|
+
description: "Label text"
|
|
25
|
+
},
|
|
26
|
+
placeholder: {
|
|
27
|
+
control: { type: "text" },
|
|
28
|
+
description: "Placeholder text"
|
|
29
|
+
},
|
|
30
|
+
description: {
|
|
31
|
+
control: { type: "text" },
|
|
32
|
+
description: "Help text below input"
|
|
33
|
+
},
|
|
34
|
+
error: {
|
|
35
|
+
control: { type: "text" },
|
|
36
|
+
description: "Error message"
|
|
37
|
+
},
|
|
38
|
+
state: {
|
|
39
|
+
control: { type: "select" },
|
|
40
|
+
options: ["default", "error", "success"],
|
|
41
|
+
description: "Visual state of the input"
|
|
42
|
+
},
|
|
43
|
+
optionalText: {
|
|
44
|
+
control: { type: "text" },
|
|
45
|
+
description: "Optional text to display next to label"
|
|
46
|
+
},
|
|
47
|
+
copyButtonLabel: {
|
|
48
|
+
control: { type: "text" },
|
|
49
|
+
description: "Label for the copy button"
|
|
50
|
+
},
|
|
51
|
+
editable: {
|
|
52
|
+
control: { type: "boolean" },
|
|
53
|
+
description: "Controls whether the input is editable"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export const Default = () => {
|
|
59
|
+
const copyProps = useCopyField({
|
|
60
|
+
onCopy: (value) => console.log("Copied:", value) // eslint-disable-line no-console
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<View style={styles.column}>
|
|
65
|
+
<View style={styles.section}>
|
|
66
|
+
<Typography size="sm" weight="semiBold" color="tertiary">
|
|
67
|
+
Using useCopyField Hook
|
|
68
|
+
</Typography>
|
|
69
|
+
<CopyField
|
|
70
|
+
{...copyProps}
|
|
71
|
+
label="API Key"
|
|
72
|
+
placeholder="Enter your API key..."
|
|
73
|
+
description="Your unique API key for authentication"
|
|
74
|
+
leadingIcon={<Icon icon={Lock} size="md" />}
|
|
75
|
+
/>
|
|
76
|
+
</View>
|
|
77
|
+
</View>
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export const States = () => {
|
|
82
|
+
const defaultProps = useCopyField()
|
|
83
|
+
const filledProps = useCopyField({ initialValue: "sk-1234567890abcdef" })
|
|
84
|
+
const errorProps = useCopyField({ initialValue: "invalid-key" })
|
|
85
|
+
const successProps = useCopyField({ initialValue: "sk-1234567890abcdef" })
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<View style={styles.column}>
|
|
89
|
+
<View style={styles.section}>
|
|
90
|
+
<Typography size="sm" weight="semiBold" color="tertiary">
|
|
91
|
+
Default State
|
|
92
|
+
</Typography>
|
|
93
|
+
<CopyField
|
|
94
|
+
{...defaultProps}
|
|
95
|
+
label="Default"
|
|
96
|
+
placeholder="Enter API key..."
|
|
97
|
+
description="Help text"
|
|
98
|
+
/>
|
|
99
|
+
</View>
|
|
100
|
+
<View style={styles.section}>
|
|
101
|
+
<Typography size="sm" weight="semiBold" color="tertiary">
|
|
102
|
+
Disabled
|
|
103
|
+
</Typography>
|
|
104
|
+
<CopyField
|
|
105
|
+
label="Disabled"
|
|
106
|
+
placeholder="Enter API key..."
|
|
107
|
+
description="Help text"
|
|
108
|
+
editable={false}
|
|
109
|
+
/>
|
|
110
|
+
</View>
|
|
111
|
+
<View style={styles.section}>
|
|
112
|
+
<Typography size="sm" weight="semiBold" color="tertiary">
|
|
113
|
+
With Value
|
|
114
|
+
</Typography>
|
|
115
|
+
<CopyField
|
|
116
|
+
{...filledProps}
|
|
117
|
+
label="With Value"
|
|
118
|
+
placeholder="Enter API key..."
|
|
119
|
+
description="Copy button enabled when field has text"
|
|
120
|
+
/>
|
|
121
|
+
</View>
|
|
122
|
+
<View style={styles.section}>
|
|
123
|
+
<Typography size="sm" weight="semiBold" color="tertiary">
|
|
124
|
+
Success State
|
|
125
|
+
</Typography>
|
|
126
|
+
<CopyField
|
|
127
|
+
{...successProps}
|
|
128
|
+
label="Success State"
|
|
129
|
+
placeholder="Enter API key..."
|
|
130
|
+
state="success"
|
|
131
|
+
description="API key verified"
|
|
132
|
+
/>
|
|
133
|
+
</View>
|
|
134
|
+
<View style={styles.section}>
|
|
135
|
+
<Typography size="sm" weight="semiBold" color="tertiary">
|
|
136
|
+
Error State
|
|
137
|
+
</Typography>
|
|
138
|
+
<CopyField
|
|
139
|
+
{...errorProps}
|
|
140
|
+
label="Error State"
|
|
141
|
+
placeholder="Enter API key..."
|
|
142
|
+
state="error"
|
|
143
|
+
error="Invalid API key format"
|
|
144
|
+
description="Help text"
|
|
145
|
+
/>
|
|
146
|
+
</View>
|
|
147
|
+
</View>
|
|
148
|
+
)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export const ManualValidation = () => {
|
|
152
|
+
const [apiKey, setApiKey] = useState("")
|
|
153
|
+
const [apiKeyState, setApiKeyState] = useState<InputState>("default")
|
|
154
|
+
|
|
155
|
+
const handleChange = (newValue: string) => {
|
|
156
|
+
setApiKey(newValue)
|
|
157
|
+
|
|
158
|
+
if (!newValue) {
|
|
159
|
+
setApiKeyState("default")
|
|
160
|
+
return
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const hasMinLength = newValue.length >= 10
|
|
164
|
+
const hasPrefix = newValue.startsWith("sk-")
|
|
165
|
+
const hasValidChars = /^sk-[a-z0-9]+$/.test(newValue)
|
|
166
|
+
|
|
167
|
+
const allRequirementsMet = hasMinLength && hasPrefix && hasValidChars
|
|
168
|
+
|
|
169
|
+
setApiKeyState(allRequirementsMet ? "success" : "error")
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return (
|
|
173
|
+
<View style={styles.column}>
|
|
174
|
+
<View style={styles.section}>
|
|
175
|
+
<Typography size="sm" weight="semiBold" color="tertiary">
|
|
176
|
+
Manual Validation with Success State
|
|
177
|
+
</Typography>
|
|
178
|
+
<CopyField
|
|
179
|
+
label="API Key"
|
|
180
|
+
placeholder="sk-xxxxxxxxxxxxxxxx"
|
|
181
|
+
value={apiKey}
|
|
182
|
+
onValueChange={handleChange}
|
|
183
|
+
onCopy={(value) => console.log("Copied:", value)} // eslint-disable-line no-console
|
|
184
|
+
state={apiKeyState}
|
|
185
|
+
description="Must start with 'sk-', at least 10 chars, lowercase letters and numbers only"
|
|
186
|
+
error="Invalid API key format"
|
|
187
|
+
/>
|
|
188
|
+
</View>
|
|
189
|
+
</View>
|
|
190
|
+
)
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export const CompoundComponentAPI = () => {
|
|
194
|
+
const [apiKey, setApiKey] = useState("")
|
|
195
|
+
const [apiKeyState, setApiKeyState] = useState<InputState>("default")
|
|
196
|
+
|
|
197
|
+
const handleChange = (newValue: string) => {
|
|
198
|
+
setApiKey(newValue)
|
|
199
|
+
|
|
200
|
+
if (!newValue) {
|
|
201
|
+
setApiKeyState("default")
|
|
202
|
+
return
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const hasMinLength = newValue.length >= 10
|
|
206
|
+
const hasPrefix = newValue.startsWith("sk-")
|
|
207
|
+
const hasValidChars = /^sk-[a-z0-9]+$/.test(newValue)
|
|
208
|
+
|
|
209
|
+
const allRequirementsMet = hasMinLength && hasPrefix && hasValidChars
|
|
210
|
+
|
|
211
|
+
setApiKeyState(allRequirementsMet ? "success" : "error")
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return (
|
|
215
|
+
<View style={styles.column}>
|
|
216
|
+
<View style={styles.section}>
|
|
217
|
+
<Typography size="sm" weight="semiBold" color="tertiary">
|
|
218
|
+
Compound Component API
|
|
219
|
+
</Typography>
|
|
220
|
+
<CopyField.Root>
|
|
221
|
+
<CopyField.Label state={apiKeyState}>API Key</CopyField.Label>
|
|
222
|
+
<CopyField.Field
|
|
223
|
+
placeholder="sk-xxxxxxxxxxxxxxxx"
|
|
224
|
+
value={apiKey}
|
|
225
|
+
onValueChange={handleChange}
|
|
226
|
+
onCopy={(value) => console.log("Copied:", value)} // eslint-disable-line no-console
|
|
227
|
+
state={apiKeyState}
|
|
228
|
+
/>
|
|
229
|
+
<CopyField.Description state={apiKeyState}>
|
|
230
|
+
Must start with 'sk-' and be at least 10 characters
|
|
231
|
+
</CopyField.Description>
|
|
232
|
+
{apiKeyState === "error" && apiKey.length > 0 && (
|
|
233
|
+
<CopyField.Error>Invalid API key format</CopyField.Error>
|
|
234
|
+
)}
|
|
235
|
+
</CopyField.Root>
|
|
236
|
+
</View>
|
|
237
|
+
</View>
|
|
238
|
+
)
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export const WithOptionalText = () => (
|
|
242
|
+
<View style={styles.column}>
|
|
243
|
+
<View style={styles.section}>
|
|
244
|
+
<Typography size="sm" weight="semiBold" color="tertiary">
|
|
245
|
+
With Optional Text
|
|
246
|
+
</Typography>
|
|
247
|
+
<CopyField
|
|
248
|
+
label="API Key"
|
|
249
|
+
optionalText="(optional)"
|
|
250
|
+
placeholder="Enter API key..."
|
|
251
|
+
description="Optional API key field"
|
|
252
|
+
/>
|
|
253
|
+
</View>
|
|
254
|
+
</View>
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
export const Controlled = () => {
|
|
258
|
+
const copyProps = useCopyField({
|
|
259
|
+
onCopy: (value) => console.log("Copied to clipboard:", value) // eslint-disable-line no-console
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
return (
|
|
263
|
+
<View style={styles.column}>
|
|
264
|
+
<View style={styles.section}>
|
|
265
|
+
<Typography size="sm" weight="semiBold" color="tertiary">
|
|
266
|
+
Controlled: {copyProps.value || "(empty)"}
|
|
267
|
+
</Typography>
|
|
268
|
+
<CopyField
|
|
269
|
+
{...copyProps}
|
|
270
|
+
label="API Key"
|
|
271
|
+
placeholder="Enter API key..."
|
|
272
|
+
description={`Current value: "${copyProps.value || "empty"}"`}
|
|
273
|
+
/>
|
|
274
|
+
</View>
|
|
275
|
+
</View>
|
|
276
|
+
)
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
export const CustomButtonLabel = () => {
|
|
280
|
+
const copyProps = useCopyField({ initialValue: "sk-1234567890abcdef" })
|
|
281
|
+
|
|
282
|
+
return (
|
|
283
|
+
<View style={styles.column}>
|
|
284
|
+
<View style={styles.section}>
|
|
285
|
+
<Typography size="sm" weight="semiBold" color="tertiary">
|
|
286
|
+
Custom Copy Button Label
|
|
287
|
+
</Typography>
|
|
288
|
+
<CopyField
|
|
289
|
+
{...copyProps}
|
|
290
|
+
label="API Key"
|
|
291
|
+
placeholder="Enter API key..."
|
|
292
|
+
copyButtonLabel="Copy Key"
|
|
293
|
+
description="Custom button label example"
|
|
294
|
+
/>
|
|
295
|
+
</View>
|
|
296
|
+
</View>
|
|
297
|
+
)
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const styles = StyleSheet.create({
|
|
301
|
+
container: {
|
|
302
|
+
width: 320
|
|
303
|
+
},
|
|
304
|
+
column: {
|
|
305
|
+
flexDirection: "column",
|
|
306
|
+
gap: 24,
|
|
307
|
+
width: 320
|
|
308
|
+
},
|
|
309
|
+
section: {
|
|
310
|
+
flexDirection: "column",
|
|
311
|
+
gap: 8
|
|
312
|
+
}
|
|
313
|
+
})
|