@butternutbox/pawprint-native 2.0.0 → 2.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 +8 -8
- package/CHANGELOG.md +18 -0
- package/dist/index.cjs +40 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +40 -26
- package/dist/index.js.map +1 -1
- package/package.json +8 -8
- package/src/components/molecules/SelectField/SelectField.stories.tsx +13 -0
- package/src/components/molecules/SelectField/SelectField.test.tsx +41 -0
- package/src/components/molecules/SelectField/SelectField.tsx +37 -21
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@butternutbox/pawprint-native",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "ButternutBox Pawprint Design System - React Native Components",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
"test": "vitest run"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@butternutbox/pawprint-fonts": "^2.0.
|
|
26
|
-
"@butternutbox/pawprint-tokens": "^0.6.
|
|
25
|
+
"@butternutbox/pawprint-fonts": "^2.0.2",
|
|
26
|
+
"@butternutbox/pawprint-tokens": "^0.6.1",
|
|
27
27
|
"@emotion/native": "^11.11.0",
|
|
28
28
|
"@emotion/react": "^11.14.0",
|
|
29
29
|
"@rn-primitives/avatar": "^1.4.0",
|
|
@@ -54,10 +54,10 @@
|
|
|
54
54
|
}
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
|
-
"@butternutbox/pawprint-icons": "
|
|
58
|
-
"@butternutbox/pawprint-illustrations": "
|
|
59
|
-
"@repo/eslint-config": "
|
|
60
|
-
"@repo/typescript-config": "
|
|
57
|
+
"@butternutbox/pawprint-icons": "1.8.1",
|
|
58
|
+
"@butternutbox/pawprint-illustrations": "3.1.1",
|
|
59
|
+
"@repo/eslint-config": "0.0.0",
|
|
60
|
+
"@repo/typescript-config": "0.0.0",
|
|
61
61
|
"@testing-library/dom": "^10.4.1",
|
|
62
62
|
"@testing-library/jest-dom": "^6.6.3",
|
|
63
63
|
"@testing-library/react": "^16.3.0",
|
|
@@ -80,4 +80,4 @@
|
|
|
80
80
|
"publishConfig": {
|
|
81
81
|
"access": "public"
|
|
82
82
|
}
|
|
83
|
-
}
|
|
83
|
+
}
|
|
@@ -151,6 +151,19 @@ export const WithOptionalText = () => (
|
|
|
151
151
|
</StoryWrapper>
|
|
152
152
|
)
|
|
153
153
|
|
|
154
|
+
export const NotSearchable = () => (
|
|
155
|
+
<StoryWrapper>
|
|
156
|
+
<Section title="Pick from the list only">
|
|
157
|
+
<SelectField
|
|
158
|
+
label="Country"
|
|
159
|
+
placeholder="Select a country"
|
|
160
|
+
searchable={false}
|
|
161
|
+
options={COUNTRIES}
|
|
162
|
+
/>
|
|
163
|
+
</Section>
|
|
164
|
+
</StoryWrapper>
|
|
165
|
+
)
|
|
166
|
+
|
|
154
167
|
export const Controlled = () => {
|
|
155
168
|
const [country, setCountry] = useState<string | null>("ca")
|
|
156
169
|
|
|
@@ -293,6 +293,47 @@ describe("SelectField", () => {
|
|
|
293
293
|
})
|
|
294
294
|
})
|
|
295
295
|
|
|
296
|
+
describe("when not searchable", () => {
|
|
297
|
+
it("can't be typed into", () => {
|
|
298
|
+
const input = renderField({ searchable: false })
|
|
299
|
+
|
|
300
|
+
expect(input).toBeDisabled()
|
|
301
|
+
})
|
|
302
|
+
|
|
303
|
+
it("stays closed until the field is pressed", () => {
|
|
304
|
+
renderField({ searchable: false })
|
|
305
|
+
|
|
306
|
+
expect(screen.queryByText("United Kingdom")).not.toBeInTheDocument()
|
|
307
|
+
})
|
|
308
|
+
|
|
309
|
+
it("shows every option when the field is pressed", () => {
|
|
310
|
+
const input = renderField({ searchable: false })
|
|
311
|
+
fireEvent.click(input)
|
|
312
|
+
|
|
313
|
+
COUNTRIES.forEach((option) => {
|
|
314
|
+
expect(screen.getByText(option.label)).toBeInTheDocument()
|
|
315
|
+
})
|
|
316
|
+
})
|
|
317
|
+
|
|
318
|
+
it("selects the pressed option and closes", () => {
|
|
319
|
+
const onValueChange = vi.fn()
|
|
320
|
+
const input = renderField({ searchable: false, onValueChange })
|
|
321
|
+
fireEvent.click(input)
|
|
322
|
+
fireEvent.click(screen.getByText("Canada"))
|
|
323
|
+
|
|
324
|
+
expect(onValueChange).toHaveBeenCalledWith("ca")
|
|
325
|
+
expect(input).toHaveValue("Canada")
|
|
326
|
+
expect(screen.queryByText("Australia")).not.toBeInTheDocument()
|
|
327
|
+
})
|
|
328
|
+
|
|
329
|
+
it("does not open when disabled", () => {
|
|
330
|
+
const input = renderField({ searchable: false, disabled: true })
|
|
331
|
+
fireEvent.click(input)
|
|
332
|
+
|
|
333
|
+
expect(screen.queryByText("United Kingdom")).not.toBeInTheDocument()
|
|
334
|
+
})
|
|
335
|
+
})
|
|
336
|
+
|
|
296
337
|
describe("controlled mode", () => {
|
|
297
338
|
it("shows the label for the controlled value", () => {
|
|
298
339
|
const input = renderField({ value: "au" })
|
|
@@ -2,6 +2,7 @@ import React from "react"
|
|
|
2
2
|
import {
|
|
3
3
|
Keyboard,
|
|
4
4
|
Pressable,
|
|
5
|
+
StyleSheet,
|
|
5
6
|
TextInput,
|
|
6
7
|
useWindowDimensions,
|
|
7
8
|
View,
|
|
@@ -40,6 +41,7 @@ type SelectFieldOwnProps = {
|
|
|
40
41
|
optionalText?: string
|
|
41
42
|
placeholder?: string
|
|
42
43
|
leadingIcon?: React.ReactNode
|
|
44
|
+
searchable?: boolean
|
|
43
45
|
noResultsText?: string
|
|
44
46
|
errorText?: string
|
|
45
47
|
onSearchQuery?: SelectOptionsResolver
|
|
@@ -73,6 +75,7 @@ export const SelectField = React.forwardRef<View, SelectFieldProps>(
|
|
|
73
75
|
optionalText,
|
|
74
76
|
placeholder,
|
|
75
77
|
leadingIcon,
|
|
78
|
+
searchable = true,
|
|
76
79
|
noResultsText = "No results found",
|
|
77
80
|
errorText = "Something went wrong",
|
|
78
81
|
onSearchQuery,
|
|
@@ -244,7 +247,7 @@ export const SelectField = React.forwardRef<View, SelectFieldProps>(
|
|
|
244
247
|
setInputText("")
|
|
245
248
|
setFilterQuery("")
|
|
246
249
|
commitValue(null)
|
|
247
|
-
inputRef.current?.focus()
|
|
250
|
+
if (searchable) inputRef.current?.focus()
|
|
248
251
|
}
|
|
249
252
|
|
|
250
253
|
const fieldState: InputState = error ? "error" : state
|
|
@@ -272,24 +275,34 @@ export const SelectField = React.forwardRef<View, SelectFieldProps>(
|
|
|
272
275
|
if (!isOpen || !anchorRect) return null
|
|
273
276
|
|
|
274
277
|
return (
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
278
|
+
<>
|
|
279
|
+
{!searchable && (
|
|
280
|
+
<Pressable
|
|
281
|
+
style={StyleSheet.absoluteFill}
|
|
282
|
+
onPress={() => setIsFocused(false)}
|
|
283
|
+
accessible={false}
|
|
284
|
+
/>
|
|
285
|
+
)}
|
|
286
|
+
<SelectFieldDropdown
|
|
287
|
+
anchor={anchorRect}
|
|
288
|
+
placement={placement.direction}
|
|
289
|
+
maxHeight={placement.maxHeight}
|
|
290
|
+
screenHeight={windowHeight}
|
|
291
|
+
accessibilityLiveRegion="polite"
|
|
292
|
+
>
|
|
293
|
+
<SelectFieldList
|
|
294
|
+
state={optionsState}
|
|
295
|
+
selectedValue={selectedValue}
|
|
296
|
+
onSelect={onOptionPress}
|
|
297
|
+
noResultsText={noResultsText}
|
|
298
|
+
errorText={errorText}
|
|
299
|
+
searchHintText={searchHintText}
|
|
300
|
+
/>
|
|
301
|
+
</SelectFieldDropdown>
|
|
302
|
+
</>
|
|
291
303
|
)
|
|
292
304
|
}, [
|
|
305
|
+
searchable,
|
|
293
306
|
isOpen,
|
|
294
307
|
anchorRect,
|
|
295
308
|
placement,
|
|
@@ -313,11 +326,14 @@ export const SelectField = React.forwardRef<View, SelectFieldProps>(
|
|
|
313
326
|
<InputField
|
|
314
327
|
ref={inputRef}
|
|
315
328
|
value={inputText}
|
|
316
|
-
onChangeText={handleChangeText}
|
|
317
|
-
onFocus={handleFocus}
|
|
318
|
-
onBlur={handleBlur}
|
|
329
|
+
onChangeText={searchable ? handleChangeText : undefined}
|
|
330
|
+
onFocus={searchable ? handleFocus : undefined}
|
|
331
|
+
onBlur={searchable ? handleBlur : undefined}
|
|
332
|
+
onPress={
|
|
333
|
+
!searchable && !disabled ? () => setIsFocused(true) : undefined
|
|
334
|
+
}
|
|
319
335
|
placeholder={placeholder}
|
|
320
|
-
editable={!disabled}
|
|
336
|
+
editable={searchable && !disabled}
|
|
321
337
|
state={fieldState}
|
|
322
338
|
hideStateIcons={Boolean(clearAction)}
|
|
323
339
|
leadingIcon={leadingIcon}
|