@forthtilliath/react-native-kit 0.18.0 → 0.20.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/README.md +60 -16
- package/dist/components/picker/PhotoPicker.d.ts +22 -29
- package/dist/components/picker/PhotoPicker.d.ts.map +1 -1
- package/dist/components/picker/PhotoPicker.js +49 -81
- package/dist/components/picker/PhotoPicker.styles.d.ts +63 -0
- package/dist/components/picker/PhotoPicker.styles.d.ts.map +1 -0
- package/dist/components/picker/PhotoPicker.styles.js +59 -0
- package/dist/components/picker/QuantityStepper.d.ts +32 -31
- package/dist/components/picker/QuantityStepper.d.ts.map +1 -1
- package/dist/components/picker/QuantityStepper.js +39 -69
- package/dist/components/picker/QuantityStepper.styles.d.ts +59 -0
- package/dist/components/picker/QuantityStepper.styles.d.ts.map +1 -0
- package/dist/components/picker/QuantityStepper.styles.js +46 -0
- package/dist/components/settings/UpdateSettingsScreen.d.ts +5 -1
- package/dist/components/settings/UpdateSettingsScreen.d.ts.map +1 -1
- package/dist/components/settings/UpdateSettingsScreen.js +3 -3
- package/dist/components/settings/UpdateSettingsScreen.styles.d.ts +2 -0
- package/dist/components/settings/UpdateSettingsScreen.styles.d.ts.map +1 -1
- package/dist/components/theme/BackgroundPicker.d.ts +46 -0
- package/dist/components/theme/BackgroundPicker.d.ts.map +1 -0
- package/dist/components/theme/BackgroundPicker.js +79 -0
- package/dist/components/theme/findBackground.d.ts +20 -0
- package/dist/components/theme/findBackground.d.ts.map +1 -0
- package/dist/components/theme/findBackground.js +12 -0
- package/dist/components/theme/index.d.ts +2 -0
- package/dist/components/theme/index.d.ts.map +1 -1
- package/dist/components/theme/index.js +2 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/useViewShare.d.ts +39 -0
- package/dist/hooks/useViewShare.d.ts.map +1 -0
- package/dist/hooks/useViewShare.js +75 -0
- package/dist/utils/helpers/shareViewAsImage.d.ts +5 -3
- package/dist/utils/helpers/shareViewAsImage.d.ts.map +1 -1
- package/dist/utils/helpers/shareViewAsImage.js +3 -1
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -211,6 +211,11 @@ import { PhotoPicker } from "@forthtilliath/react-native-kit/components/picker/P
|
|
|
211
211
|
/>;
|
|
212
212
|
```
|
|
213
213
|
|
|
214
|
+
- `renderPreview(photoUri, saving)` replaces the square preview and the "Add a photo" placeholder (e.g. a round avatar with initials and a small camera badge); the press, permission and action sheet stay the same.
|
|
215
|
+
- While `savePhoto` runs, the picker ignores presses (`saving` is `true`, `accessibilityState.busy`).
|
|
216
|
+
- `onOpen()` fires when a press opens the camera/library choice — the place for a haptic tick (`onOpen={tapFeedback}`).
|
|
217
|
+
- A failure (camera, picker or `savePhoto` rejecting) goes to `onError(error)`; without it, an alert says the photo was not saved (`labels.saveErrorTitle` / `saveErrorMessage`).
|
|
218
|
+
|
|
214
219
|
### `<PickerModal visible title items onSelect onClose />`
|
|
215
220
|
|
|
216
221
|
Full-screen picker: search (typed or dictated via `VoiceSearchButton`), optional sections, and "add" actions always visible above the results.
|
|
@@ -292,6 +297,25 @@ const repeat = usePressRepeat();
|
|
|
292
297
|
/>;
|
|
293
298
|
```
|
|
294
299
|
|
|
300
|
+
### `useViewShare(options?)`
|
|
301
|
+
|
|
302
|
+
Shares as an image a view rendered only for the capture (a scoreboard, a summary card): `share()` sets `capturing` to `true`, waits two frames for the screen to mount and draw the view attached to `ref`, then calls `shareViewAsImage`. A failure shows an alert with the error's message (French or English titles, `errorTitle` / `errorMessage` to override), or goes to `onError(error)`. A second `share()` while one runs is ignored. Takes `shareViewAsImage`'s options (`dialogTitle`…).
|
|
303
|
+
|
|
304
|
+
```tsx
|
|
305
|
+
import { useViewShare } from "@forthtilliath/react-native-kit/hooks/useViewShare";
|
|
306
|
+
|
|
307
|
+
const ranking = useViewShare({ dialogTitle: "Partager le classement" });
|
|
308
|
+
|
|
309
|
+
<Button title="Partager" onPress={() => void ranking.share()} />;
|
|
310
|
+
{
|
|
311
|
+
ranking.capturing ? (
|
|
312
|
+
<View ref={ranking.ref} collapsable={false} style={offScreen}>
|
|
313
|
+
<RankingCard />
|
|
314
|
+
</View>
|
|
315
|
+
) : null;
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
|
|
295
319
|
### `confirmDestructive(title, onConfirm, options?)`
|
|
296
320
|
|
|
297
321
|
Generic destructive-action confirmation (title + message + Cancel/Confirm), for anything irreversible (delete, reset...). Ships with French defaults, or English ones with `{ locale: "en" }` (`message`, `cancelLabel`, `confirmLabel` all overridable).
|
|
@@ -336,6 +360,26 @@ import { ThemeOptionList } from "@forthtilliath/react-native-kit/components/them
|
|
|
336
360
|
<ThemeOptionList value={themePreference} onChange={setThemePreference} />;
|
|
337
361
|
```
|
|
338
362
|
|
|
363
|
+
### `<BackgroundPicker options value onChange />` + `findBackground(options, id)`
|
|
364
|
+
|
|
365
|
+
Radio group of background swatches, each drawing the page and a card in the colours on offer (`{ id, label, page, card, cardBorder? }`), the chosen one outlined with a check mark. `onChange` receives the whole option (extra fields kept: the full palette to apply). `findBackground` reads a saved id back, falling back to the first option (the original background) for an unknown id. Check each palette's text contrast in a test with `contrastRatio` from `@forthtilliath/ts-kit/color/contrastRatio`.
|
|
366
|
+
|
|
367
|
+
```tsx
|
|
368
|
+
import { BackgroundPicker } from "@forthtilliath/react-native-kit/components/theme/BackgroundPicker";
|
|
369
|
+
import { findBackground } from "@forthtilliath/react-native-kit/components/theme/findBackground";
|
|
370
|
+
|
|
371
|
+
const background = findBackground(DARK_BACKGROUNDS, settings.background);
|
|
372
|
+
|
|
373
|
+
<BackgroundPicker
|
|
374
|
+
options={DARK_BACKGROUNDS}
|
|
375
|
+
value={background.id}
|
|
376
|
+
onChange={(option) => {
|
|
377
|
+
selectFeedback();
|
|
378
|
+
saveBackground(option.id);
|
|
379
|
+
}}
|
|
380
|
+
/>;
|
|
381
|
+
```
|
|
382
|
+
|
|
339
383
|
### `<ThemePreferenceProvider load save>` + `useThemePreference()` / `useResolvedScheme()`
|
|
340
384
|
|
|
341
385
|
Holds the light/dark/system preference in a context: loaded once on mount through `load`, changed from anywhere with `useThemePreference().setPreference`, persisted through `save`. Storage-agnostic. A choice made before `load` resolves isn't overwritten by the stored value. `useResolvedScheme()` returns the scheme actually applied (`"light" | "dark"`), to pick the palette.
|
|
@@ -358,20 +402,20 @@ const colors = Colors[useResolvedScheme()];
|
|
|
358
402
|
|
|
359
403
|
Every component below has neutral default colors and a `styles` prop whose slots are each merged **after** their default (a partial override keeps the rest of the slot) — pass the app's palette there.
|
|
360
404
|
|
|
361
|
-
| Component | Import path | What it is
|
|
362
|
-
| ----------------------------------------------------------------------- | ----------------------------------- |
|
|
363
|
-
| `<BottomSheet visible onClose bottomInset?>` | `components/overlay/BottomSheet` | Modal sliding up from the bottom, content scrollable past 85 % of the screen. Pass `useSafeAreaInsets().bottom` as `bottomInset` with Android edge-to-edge.
|
|
364
|
-
| `<OptionsModal visible onClose options onSelect>` | `components/picker/OptionsModal` | Centered popup listing `{ value, label }` options; a tap selects and closes.
|
|
365
|
-
| `<SelectField label valueLabel options onSelect>` | `components/picker/SelectField` | Native-looking "select": captioned button + `OptionsModal` (styled through `styles.optionsModal`).
|
|
366
|
-
| `<SegmentedToggle options value onChange label?>` | `components/picker/SegmentedToggle` | Row of equal-width buttons, one active (Calendar / List…), announced as a radio group; each option may carry a smaller `hint` line under its label.
|
|
367
|
-
| `<QuantityStepper value onChange label min? max?>` | `components/picker/QuantityStepper` | Whole-number counter `min…max` (`0…999`, negatives allowed with a negative `min`): −/+ buttons (disabled at the bounds, `longPressStep` to jump on long press, or `repeatOnHold` to repeat faster and faster while held) and a numeric field; screen-reader labels in French or English (`a11yLabels` to override). |
|
|
368
|
-
| `<SwitchRow label description? value onChange>` | `components/settings/SwitchRow` | Settings line "label + description + switch", the whole row pressable and read as one switch; `colors` for the track and thumb.
|
|
369
|
-
| `<SettingsCard title icon?>` + `SettingsCardStatus`, `SettingsCardHint` | `components/settings/SettingsCard` | Settings card: icon + title header, then free content — status lines (small icon + text, `iconColor` per state) and a quieter hint.
|
|
370
|
-
| `<CheckboxGroup options values onChange label?>` | `components/picker/CheckboxGroup` | Wrapping chips that each check and uncheck independently (extensions, tags…), each announced as a checkbox.
|
|
371
|
-
| `<MonthDayGrid days selected onToggle>` | `components/picker/MonthDayGrid` | Monday-first month grid whose days toggle on and off (holidays, days off…); `YYYY-MM-DD` days.
|
|
372
|
-
| `<AddButton label onPress>` | `components/list/AddButton` | Dashed "+ Add …" button closing a list.
|
|
373
|
-
| `<DragHandle onPressIn accessibilityLabel>` | `components/list/DragHandle` | "⠿" grip for `react-native-draggable-flatlist` rows (gesture-handler's `Pressable`).
|
|
374
|
-
| `<ErrorFallback error retry>` | `components/feedback/ErrorFallback` | Readable crash screen with a retry button, for Expo Router's `ErrorBoundary`; texts in French or English (`labels` to override).
|
|
405
|
+
| Component | Import path | What it is |
|
|
406
|
+
| ----------------------------------------------------------------------- | ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
407
|
+
| `<BottomSheet visible onClose bottomInset?>` | `components/overlay/BottomSheet` | Modal sliding up from the bottom, content scrollable past 85 % of the screen. Pass `useSafeAreaInsets().bottom` as `bottomInset` with Android edge-to-edge. |
|
|
408
|
+
| `<OptionsModal visible onClose options onSelect>` | `components/picker/OptionsModal` | Centered popup listing `{ value, label }` options; a tap selects and closes. |
|
|
409
|
+
| `<SelectField label valueLabel options onSelect>` | `components/picker/SelectField` | Native-looking "select": captioned button + `OptionsModal` (styled through `styles.optionsModal`). |
|
|
410
|
+
| `<SegmentedToggle options value onChange label?>` | `components/picker/SegmentedToggle` | Row of equal-width buttons, one active (Calendar / List…), announced as a radio group; each option may carry a smaller `hint` line under its label. |
|
|
411
|
+
| `<QuantityStepper value onChange label min? max?>` | `components/picker/QuantityStepper` | Whole-number counter `min…max` (`0…999`, negatives allowed with a negative `min`, `-Infinity`/`Infinity` for no bound): −/+ buttons moving by `step` (1; disabled at the bounds, `longPressStep` to jump on long press, or `repeatOnHold` to repeat faster and faster while held) and a numeric field; `onStep(value)` fires on each −/+ change (e.g. `onStep={tapFeedback}`), not on typing; `maxFontSizeMultiplier` caps the system font scaling of −, + and the field; screen-reader labels in French or English (`a11yLabels` to override). |
|
|
412
|
+
| `<SwitchRow label description? value onChange>` | `components/settings/SwitchRow` | Settings line "label + description + switch", the whole row pressable and read as one switch; `colors` for the track and thumb. |
|
|
413
|
+
| `<SettingsCard title icon?>` + `SettingsCardStatus`, `SettingsCardHint` | `components/settings/SettingsCard` | Settings card: icon + title header, then free content — status lines (small icon + text, `iconColor` per state) and a quieter hint. |
|
|
414
|
+
| `<CheckboxGroup options values onChange label?>` | `components/picker/CheckboxGroup` | Wrapping chips that each check and uncheck independently (extensions, tags…), each announced as a checkbox. |
|
|
415
|
+
| `<MonthDayGrid days selected onToggle>` | `components/picker/MonthDayGrid` | Monday-first month grid whose days toggle on and off (holidays, days off…); `YYYY-MM-DD` days. |
|
|
416
|
+
| `<AddButton label onPress>` | `components/list/AddButton` | Dashed "+ Add …" button closing a list. |
|
|
417
|
+
| `<DragHandle onPressIn accessibilityLabel>` | `components/list/DragHandle` | "⠿" grip for `react-native-draggable-flatlist` rows (gesture-handler's `Pressable`). |
|
|
418
|
+
| `<ErrorFallback error retry>` | `components/feedback/ErrorFallback` | Readable crash screen with a retry button, for Expo Router's `ErrorBoundary`; texts in French or English (`labels` to override). |
|
|
375
419
|
|
|
376
420
|
`SwipeableRow` also takes `fullSwipeToDelete`: swiping past half the row deletes right away (the row slides out over a full-width delete band) instead of revealing a button — pair it with an `UndoToast`.
|
|
377
421
|
|
|
@@ -516,7 +560,7 @@ import { ThemeSettingsScreen } from "@forthtilliath/react-native-kit/components/
|
|
|
516
560
|
|
|
517
561
|
#### `<UpdateSettingsScreen currentVersion checkForUpdate compareVersions downloadAndInstallApk />`
|
|
518
562
|
|
|
519
|
-
The full "check for update" screen: installed version, a manual check button, the available-update box (changelog + install button) or an up-to-date/error message, download progress, and — if `fetchReleaseHistory` is passed — a list of past releases. Checks automatically once on mount. Renders release notes via `@forthtilliath/expo-release-updates-ui`'s `ChangelogNotes`, and pairs naturally with that package's `useUpdateCheck`/`UpdateAvailableBanner` (same `checkForUpdate`/`compareVersions` you already pass those), but takes plain functions so it isn't tied to that package's exact shape. `@forthtilliath/expo-release-updates-ui` is an optional peer dependency: install it to use this screen.
|
|
563
|
+
The full "check for update" screen: installed version, a manual check button, the available-update box (changelog + install button) or an up-to-date/error message, download progress, and — if `fetchReleaseHistory` is passed — a list of past releases. Checks automatically once on mount. Renders release notes via `@forthtilliath/expo-release-updates-ui`'s `ChangelogNotes`, and pairs naturally with that package's `useUpdateCheck`/`UpdateAvailableBanner` (same `checkForUpdate`/`compareVersions` you already pass those), but takes plain functions so it isn't tied to that package's exact shape. `@forthtilliath/expo-release-updates-ui` is an optional peer dependency: install it to use this screen. `downloadAndInstallApk(apkUrl, onProgress, apkSha256)` receives the release's `apkSha256` (from `fetchLatestRelease`): pass it on as `expectedSha256`.
|
|
520
564
|
|
|
521
565
|
```tsx
|
|
522
566
|
import { UpdateSettingsScreen } from "@forthtilliath/react-native-kit/components/settings/UpdateSettingsScreen";
|
|
@@ -652,7 +696,7 @@ For all 7 components above, styling works the same way as `ChangelogNotes`: an o
|
|
|
652
696
|
- `mergeSlotStyles(defaultStyles, styles)` — merges a component's per-slot `styles` overrides onto its defaults as `[default, override]` style arrays, so overriding one property of a slot keeps the rest of its default. Every component of this package uses it; handy for your own components following the same `styles` convention.
|
|
653
697
|
- `shareFile(uri, { mimeType, dialogTitle?, locale? })` — opens the native share sheet for a local file; throws a user-facing `Error` (French, or English with `locale: "en"`) when the device can't share. Needs `expo-sharing`.
|
|
654
698
|
- `shareTextFile(filename, content, options)` — writes the text to a file in the cache (replacing any previous one), then `shareFile`s it: `.ics`, `.csv`, JSON exports… Needs `expo-file-system` and `expo-sharing`.
|
|
655
|
-
- `shareViewAsImage(ref, { dialogTitle?, locale? })` (`utils/helpers/shareViewAsImage`) — captures a view as a PNG and shares it (scoreboard, schedule…). Needs `react-native-view-shot` and `expo-sharing`; the capture library is loaded on demand, so a binary built without it only fails this call, with a user-facing `Error`.
|
|
699
|
+
- `shareViewAsImage(ref, { dialogTitle?, locale? })` (`utils/helpers/shareViewAsImage`) — captures a view as a PNG and shares it (scoreboard, schedule…); `ref` is a `RefObject<ComponentRef<typeof View> | null>`, as `useRef<ComponentRef<typeof View>>(null)` gives. Needs `react-native-view-shot` and `expo-sharing`; the capture library is loaded on demand, so a binary built without it only fails this call, with a user-facing `Error`.
|
|
656
700
|
- `isNativeModuleAvailable(name)` — whether a native module is compiled into this binary (either architecture): check it before loading a library that crashes on import without its module.
|
|
657
701
|
|
|
658
702
|
### Calendar (`utils/calendar/`)
|
|
@@ -1,38 +1,31 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
2
|
import { type KitLocale } from "../../i18n/locale.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
photoPreview?: StyleProp<ImageStyle>;
|
|
6
|
-
photoPlaceholder?: StyleProp<ViewStyle>;
|
|
7
|
-
photoPlaceholderText?: StyleProp<TextStyle>;
|
|
8
|
-
clearLink?: StyleProp<TextStyle>;
|
|
9
|
-
iconColor?: string;
|
|
10
|
-
}
|
|
11
|
-
export interface PhotoPickerLabels {
|
|
12
|
-
photoTitle?: (photoLabel: string) => string;
|
|
13
|
-
editAccessibilityLabel?: (photoLabel: string) => string;
|
|
14
|
-
addAccessibilityLabel?: (photoLabel: string) => string;
|
|
15
|
-
addPlaceholderText?: string;
|
|
16
|
-
cameraPermissionTitle?: string;
|
|
17
|
-
cameraPermissionMessage?: string;
|
|
18
|
-
/**
|
|
19
|
-
* @deprecated Unused: choosing from the library needs no permission (the
|
|
20
|
-
* system photo picker), so no "access denied" alert is ever shown.
|
|
21
|
-
*/
|
|
22
|
-
libraryPermissionTitle?: string;
|
|
23
|
-
/** @deprecated Unused — see `libraryPermissionTitle`. */
|
|
24
|
-
libraryPermissionMessage?: string;
|
|
25
|
-
takePhoto?: string;
|
|
26
|
-
chooseFromLibrary?: string;
|
|
27
|
-
cancel?: string;
|
|
28
|
-
removePhoto?: string;
|
|
29
|
-
}
|
|
3
|
+
import { type PhotoPickerLabels, type PhotoPickerStyles } from "./PhotoPicker.styles.js";
|
|
4
|
+
export type { PhotoPickerLabels, PhotoPickerStyles, } from "./PhotoPicker.styles.js";
|
|
30
5
|
export interface PhotoPickerProps {
|
|
31
6
|
photoUri: string | null;
|
|
32
7
|
onChange: (uri: string | null) => void;
|
|
33
8
|
savePhoto: (sourceUri: string) => Promise<string>;
|
|
34
9
|
/** Used as-is in titles/accessibility labels, e.g. "of the container". */
|
|
35
10
|
photoLabel: string;
|
|
11
|
+
/**
|
|
12
|
+
* Replaces the square preview and the "Add a photo" placeholder, e.g. a
|
|
13
|
+
* round avatar with a small camera badge. `saving` is `true` while
|
|
14
|
+
* `savePhoto` runs (the picker ignores presses meanwhile).
|
|
15
|
+
*/
|
|
16
|
+
renderPreview?: (photoUri: string | null, saving: boolean) => ReactNode;
|
|
17
|
+
/**
|
|
18
|
+
* Called when taking, picking or saving the photo fails (`savePhoto`
|
|
19
|
+
* rejected…). Unset, an alert says the photo was not saved
|
|
20
|
+
* (`labels.saveErrorTitle` / `saveErrorMessage`).
|
|
21
|
+
*/
|
|
22
|
+
onError?: (error: unknown) => void;
|
|
23
|
+
/**
|
|
24
|
+
* Called when a press opens the camera/library choice (not while a photo
|
|
25
|
+
* is being saved). The place for a haptic tick: `onOpen={tapFeedback}`
|
|
26
|
+
* (from `utils/helpers/haptics`).
|
|
27
|
+
*/
|
|
28
|
+
onOpen?: () => void;
|
|
36
29
|
labels?: PhotoPickerLabels;
|
|
37
30
|
/**
|
|
38
31
|
* Language of the built-in labels — French by default, or the nearest
|
|
@@ -41,5 +34,5 @@ export interface PhotoPickerProps {
|
|
|
41
34
|
locale?: KitLocale;
|
|
42
35
|
styles?: PhotoPickerStyles;
|
|
43
36
|
}
|
|
44
|
-
export declare function PhotoPicker({ photoUri, onChange, savePhoto, photoLabel, labels, locale, styles, }: PhotoPickerProps): import("react").JSX.Element;
|
|
37
|
+
export declare function PhotoPicker({ photoUri, onChange, savePhoto, photoLabel, renderPreview, onError, onOpen, labels, locale, styles, }: PhotoPickerProps): import("react").JSX.Element;
|
|
45
38
|
//# sourceMappingURL=PhotoPicker.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PhotoPicker.d.ts","sourceRoot":"","sources":["../../../src/components/picker/PhotoPicker.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"PhotoPicker.d.ts","sourceRoot":"","sources":["../../../src/components/picker/PhotoPicker.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAoB,MAAM,OAAO,CAAC;AAKzD,OAAO,EAAE,KAAK,SAAS,EAAgB,MAAM,sBAAsB,CAAC;AAGpE,OAAO,EAGL,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACvB,MAAM,yBAAyB,CAAC;AAEjC,YAAY,EACV,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,yBAAyB,CAAC;AAEjC,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACvC,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAClD,0EAA0E;IAC1E,UAAU,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,OAAO,KAAK,SAAS,CAAC;IACxE;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B;;;OAGG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,MAAM,CAAC,EAAE,iBAAiB,CAAC;CAC5B;AAUD,wBAAgB,WAAW,CAAC,EAC1B,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,UAAU,EACV,aAAa,EACb,OAAO,EACP,MAAM,EACN,MAAM,EACN,MAAM,EACN,MAAM,GACP,EAAE,gBAAgB,+BAoHlB"}
|
|
@@ -1,121 +1,89 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useRef, useState } from "react";
|
|
2
3
|
import { Alert, Image, Pressable, Text, View } from "react-native";
|
|
3
4
|
import { Ionicons } from "@expo/vector-icons";
|
|
4
5
|
import * as ImagePicker from "expo-image-picker";
|
|
5
6
|
import { useKitLocale } from "../../i18n/locale.js";
|
|
6
7
|
import { mergeSlotStyles } from "../../utils/helpers/mergeSlotStyles.js";
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
backgroundColor: "#f9fafb",
|
|
14
|
-
},
|
|
15
|
-
photoPlaceholder: {
|
|
16
|
-
width: 140,
|
|
17
|
-
height: 140,
|
|
18
|
-
borderRadius: 16,
|
|
19
|
-
borderWidth: 1,
|
|
20
|
-
borderStyle: "dashed",
|
|
21
|
-
borderColor: "#e5e7eb",
|
|
22
|
-
backgroundColor: "#f9fafb",
|
|
23
|
-
alignItems: "center",
|
|
24
|
-
justifyContent: "center",
|
|
25
|
-
gap: 6,
|
|
26
|
-
},
|
|
27
|
-
photoPlaceholderText: { fontSize: 12, color: "#6b7280" },
|
|
28
|
-
clearLink: {
|
|
29
|
-
color: "#2563eb",
|
|
30
|
-
fontSize: 13,
|
|
31
|
-
textAlign: "center",
|
|
32
|
-
marginTop: 8,
|
|
33
|
-
},
|
|
34
|
-
iconColor: "#6b7280",
|
|
35
|
-
};
|
|
36
|
-
const defaultLabels = {
|
|
37
|
-
fr: {
|
|
38
|
-
photoTitle: (photoLabel) => `Photo ${photoLabel}`,
|
|
39
|
-
editAccessibilityLabel: (photoLabel) => `Photo ${photoLabel}. Modifier.`,
|
|
40
|
-
addAccessibilityLabel: (photoLabel) => `Ajouter une photo ${photoLabel}`,
|
|
41
|
-
addPlaceholderText: "Ajouter une photo",
|
|
42
|
-
cameraPermissionTitle: "Accès à l'appareil photo refusé",
|
|
43
|
-
cameraPermissionMessage: "Autorise l'accès dans les réglages du téléphone pour prendre une photo.",
|
|
44
|
-
takePhoto: "Prendre une photo",
|
|
45
|
-
chooseFromLibrary: "Choisir dans la galerie",
|
|
46
|
-
cancel: "Annuler",
|
|
47
|
-
removePhoto: "Retirer la photo",
|
|
48
|
-
},
|
|
49
|
-
en: {
|
|
50
|
-
photoTitle: (photoLabel) => `Photo ${photoLabel}`,
|
|
51
|
-
editAccessibilityLabel: (photoLabel) => `Photo ${photoLabel}. Edit.`,
|
|
52
|
-
addAccessibilityLabel: (photoLabel) => `Add a photo ${photoLabel}`,
|
|
53
|
-
addPlaceholderText: "Add a photo",
|
|
54
|
-
cameraPermissionTitle: "Camera access denied",
|
|
55
|
-
cameraPermissionMessage: "Allow access in the phone's settings to take a photo.",
|
|
56
|
-
takePhoto: "Take a photo",
|
|
57
|
-
chooseFromLibrary: "Choose from library",
|
|
58
|
-
cancel: "Cancel",
|
|
59
|
-
removePhoto: "Remove photo",
|
|
60
|
-
},
|
|
8
|
+
import { defaultLabels, defaultStyles, } from "./PhotoPicker.styles.js";
|
|
9
|
+
const PICKER_OPTIONS = {
|
|
10
|
+
mediaTypes: "images",
|
|
11
|
+
quality: 0.5,
|
|
12
|
+
allowsEditing: true,
|
|
13
|
+
aspect: [1, 1],
|
|
61
14
|
};
|
|
62
15
|
// Photo picker (camera or library) with a preview.
|
|
63
|
-
export function PhotoPicker({ photoUri, onChange, savePhoto, photoLabel, labels, locale, styles, }) {
|
|
16
|
+
export function PhotoPicker({ photoUri, onChange, savePhoto, photoLabel, renderPreview, onError, onOpen, labels, locale, styles, }) {
|
|
64
17
|
const mergedStyles = {
|
|
65
18
|
...mergeSlotStyles(defaultStyles, styles),
|
|
66
19
|
iconColor: styles?.iconColor ?? defaultStyles.iconColor,
|
|
67
20
|
};
|
|
68
21
|
const t = { ...defaultLabels[useKitLocale(locale)], ...labels };
|
|
69
|
-
|
|
22
|
+
const [saving, setSaving] = useState(false);
|
|
23
|
+
// Ahead of `saving`, which only changes on the next render: a second press
|
|
24
|
+
// in the same frame must not start a second save.
|
|
25
|
+
const busyRef = useRef(false);
|
|
26
|
+
async function pick(launch) {
|
|
27
|
+
if (busyRef.current)
|
|
28
|
+
return;
|
|
29
|
+
busyRef.current = true;
|
|
30
|
+
try {
|
|
31
|
+
const result = await launch();
|
|
32
|
+
const asset = result && !result.canceled ? result.assets[0] : undefined;
|
|
33
|
+
if (!asset)
|
|
34
|
+
return;
|
|
35
|
+
setSaving(true);
|
|
36
|
+
onChange(await savePhoto(asset.uri));
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
if (onError)
|
|
40
|
+
onError(error);
|
|
41
|
+
else
|
|
42
|
+
Alert.alert(t.saveErrorTitle, t.saveErrorMessage);
|
|
43
|
+
}
|
|
44
|
+
finally {
|
|
45
|
+
busyRef.current = false;
|
|
46
|
+
setSaving(false);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async function launchCamera() {
|
|
70
50
|
const permission = await ImagePicker.requestCameraPermissionsAsync();
|
|
71
51
|
if (!permission.granted) {
|
|
72
52
|
Alert.alert(t.cameraPermissionTitle, t.cameraPermissionMessage);
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
const result = await ImagePicker.launchCameraAsync({
|
|
76
|
-
mediaTypes: "images",
|
|
77
|
-
quality: 0.5,
|
|
78
|
-
allowsEditing: true,
|
|
79
|
-
aspect: [1, 1],
|
|
80
|
-
});
|
|
81
|
-
if (!result.canceled && result.assets[0]) {
|
|
82
|
-
onChange(await savePhoto(result.assets[0].uri));
|
|
53
|
+
return null;
|
|
83
54
|
}
|
|
55
|
+
return ImagePicker.launchCameraAsync(PICKER_OPTIONS);
|
|
84
56
|
}
|
|
85
57
|
// No permission request: the library is opened through the system photo
|
|
86
58
|
// picker, which needs none — so apps don't have to keep the storage
|
|
87
59
|
// permissions just for this.
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
mediaTypes: "images",
|
|
91
|
-
quality: 0.5,
|
|
92
|
-
allowsEditing: true,
|
|
93
|
-
aspect: [1, 1],
|
|
94
|
-
});
|
|
95
|
-
if (!result.canceled && result.assets[0]) {
|
|
96
|
-
onChange(await savePhoto(result.assets[0].uri));
|
|
97
|
-
}
|
|
60
|
+
function launchLibrary() {
|
|
61
|
+
return ImagePicker.launchImageLibraryAsync(PICKER_OPTIONS);
|
|
98
62
|
}
|
|
99
63
|
function handlePickPhoto() {
|
|
64
|
+
if (busyRef.current)
|
|
65
|
+
return;
|
|
66
|
+
onOpen?.();
|
|
100
67
|
Alert.alert(t.photoTitle(photoLabel), undefined, [
|
|
101
68
|
{
|
|
102
69
|
text: t.takePhoto,
|
|
103
70
|
onPress: () => {
|
|
104
|
-
void
|
|
71
|
+
void pick(launchCamera);
|
|
105
72
|
},
|
|
106
73
|
},
|
|
107
74
|
{
|
|
108
75
|
text: t.chooseFromLibrary,
|
|
109
76
|
onPress: () => {
|
|
110
|
-
void
|
|
77
|
+
void pick(launchLibrary);
|
|
111
78
|
},
|
|
112
79
|
},
|
|
113
80
|
{ text: t.cancel, style: "cancel" },
|
|
114
81
|
]);
|
|
115
82
|
}
|
|
116
|
-
|
|
83
|
+
const defaultPreview = photoUri ? (_jsx(Image, { source: { uri: photoUri }, style: mergedStyles.photoPreview, accessibilityIgnoresInvertColors: true })) : (_jsxs(View, { style: mergedStyles.photoPlaceholder, children: [_jsx(Ionicons, { name: "camera-outline", size: 28, color: mergedStyles.iconColor }), _jsx(Text, { style: mergedStyles.photoPlaceholderText, children: t.addPlaceholderText })] }));
|
|
84
|
+
return (_jsxs(_Fragment, { children: [_jsx(Pressable, { style: mergedStyles.photoPicker, onPress: handlePickPhoto, disabled: saving, accessibilityRole: "button", accessibilityState: { busy: saving, disabled: saving }, accessibilityLabel: photoUri
|
|
117
85
|
? t.editAccessibilityLabel(photoLabel)
|
|
118
|
-
: t.addAccessibilityLabel(photoLabel), children:
|
|
86
|
+
: t.addAccessibilityLabel(photoLabel), children: renderPreview ? renderPreview(photoUri, saving) : defaultPreview }), photoUri ? (_jsx(Pressable, { onPress: () => {
|
|
119
87
|
onChange(null);
|
|
120
|
-
}, accessibilityRole: "button", accessibilityLabel: t.removePhoto, children: _jsx(Text, { style: mergedStyles.clearLink, children: t.removePhoto }) })) : null] }));
|
|
88
|
+
}, disabled: saving, accessibilityRole: "button", accessibilityLabel: t.removePhoto, children: _jsx(Text, { style: mergedStyles.clearLink, children: t.removePhoto }) })) : null] }));
|
|
121
89
|
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { ImageStyle, StyleProp, TextStyle, ViewStyle } from "react-native";
|
|
2
|
+
export interface PhotoPickerStyles {
|
|
3
|
+
photoPicker?: StyleProp<ViewStyle>;
|
|
4
|
+
photoPreview?: StyleProp<ImageStyle>;
|
|
5
|
+
photoPlaceholder?: StyleProp<ViewStyle>;
|
|
6
|
+
photoPlaceholderText?: StyleProp<TextStyle>;
|
|
7
|
+
clearLink?: StyleProp<TextStyle>;
|
|
8
|
+
iconColor?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface PhotoPickerLabels {
|
|
11
|
+
photoTitle?: (photoLabel: string) => string;
|
|
12
|
+
editAccessibilityLabel?: (photoLabel: string) => string;
|
|
13
|
+
addAccessibilityLabel?: (photoLabel: string) => string;
|
|
14
|
+
addPlaceholderText?: string;
|
|
15
|
+
cameraPermissionTitle?: string;
|
|
16
|
+
cameraPermissionMessage?: string;
|
|
17
|
+
/**
|
|
18
|
+
* @deprecated Unused: choosing from the library needs no permission (the
|
|
19
|
+
* system photo picker), so no "access denied" alert is ever shown.
|
|
20
|
+
*/
|
|
21
|
+
libraryPermissionTitle?: string;
|
|
22
|
+
/** @deprecated Unused — see `libraryPermissionTitle`. */
|
|
23
|
+
libraryPermissionMessage?: string;
|
|
24
|
+
takePhoto?: string;
|
|
25
|
+
chooseFromLibrary?: string;
|
|
26
|
+
cancel?: string;
|
|
27
|
+
removePhoto?: string;
|
|
28
|
+
/** Alert shown when the photo could not be taken or saved (no `onError`). */
|
|
29
|
+
saveErrorTitle?: string;
|
|
30
|
+
saveErrorMessage?: string;
|
|
31
|
+
}
|
|
32
|
+
export declare const defaultStyles: Required<PhotoPickerStyles>;
|
|
33
|
+
export declare const defaultLabels: {
|
|
34
|
+
fr: {
|
|
35
|
+
photoTitle: (photoLabel: string) => string;
|
|
36
|
+
editAccessibilityLabel: (photoLabel: string) => string;
|
|
37
|
+
addAccessibilityLabel: (photoLabel: string) => string;
|
|
38
|
+
addPlaceholderText: string;
|
|
39
|
+
cameraPermissionTitle: string;
|
|
40
|
+
cameraPermissionMessage: string;
|
|
41
|
+
takePhoto: string;
|
|
42
|
+
chooseFromLibrary: string;
|
|
43
|
+
cancel: string;
|
|
44
|
+
removePhoto: string;
|
|
45
|
+
saveErrorTitle: string;
|
|
46
|
+
saveErrorMessage: string;
|
|
47
|
+
};
|
|
48
|
+
en: {
|
|
49
|
+
photoTitle: (photoLabel: string) => string;
|
|
50
|
+
editAccessibilityLabel: (photoLabel: string) => string;
|
|
51
|
+
addAccessibilityLabel: (photoLabel: string) => string;
|
|
52
|
+
addPlaceholderText: string;
|
|
53
|
+
cameraPermissionTitle: string;
|
|
54
|
+
cameraPermissionMessage: string;
|
|
55
|
+
takePhoto: string;
|
|
56
|
+
chooseFromLibrary: string;
|
|
57
|
+
cancel: string;
|
|
58
|
+
removePhoto: string;
|
|
59
|
+
saveErrorTitle: string;
|
|
60
|
+
saveErrorMessage: string;
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
//# sourceMappingURL=PhotoPicker.styles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PhotoPicker.styles.d.ts","sourceRoot":"","sources":["../../../src/components/picker/PhotoPicker.styles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAIhF,MAAM,WAAW,iBAAiB;IAChC,WAAW,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACnC,YAAY,CAAC,EAAE,SAAS,CAAC,UAAU,CAAC,CAAC;IACrC,gBAAgB,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACxC,oBAAoB,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC5C,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,UAAU,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,CAAC;IAC5C,sBAAsB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,CAAC;IACxD,qBAAqB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,CAAC;IACvD,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,yDAAyD;IACzD,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,eAAO,MAAM,aAAa,EAAE,QAAQ,CAAC,iBAAiB,CA4BrD,CAAC;AAEF,eAAO,MAAM,aAAa;;iCAEG,MAAM;6CACM,MAAM;4CAEP,MAAM;;;;;;;;;;;;iCAcjB,MAAM;6CACM,MAAM;4CAEP,MAAM;;;;;;;;;;;CAoB7C,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export const defaultStyles = {
|
|
2
|
+
photoPicker: { alignSelf: "center", marginTop: 8 },
|
|
3
|
+
photoPreview: {
|
|
4
|
+
width: 140,
|
|
5
|
+
height: 140,
|
|
6
|
+
borderRadius: 16,
|
|
7
|
+
backgroundColor: "#f9fafb",
|
|
8
|
+
},
|
|
9
|
+
photoPlaceholder: {
|
|
10
|
+
width: 140,
|
|
11
|
+
height: 140,
|
|
12
|
+
borderRadius: 16,
|
|
13
|
+
borderWidth: 1,
|
|
14
|
+
borderStyle: "dashed",
|
|
15
|
+
borderColor: "#e5e7eb",
|
|
16
|
+
backgroundColor: "#f9fafb",
|
|
17
|
+
alignItems: "center",
|
|
18
|
+
justifyContent: "center",
|
|
19
|
+
gap: 6,
|
|
20
|
+
},
|
|
21
|
+
photoPlaceholderText: { fontSize: 12, color: "#6b7280" },
|
|
22
|
+
clearLink: {
|
|
23
|
+
color: "#2563eb",
|
|
24
|
+
fontSize: 13,
|
|
25
|
+
textAlign: "center",
|
|
26
|
+
marginTop: 8,
|
|
27
|
+
},
|
|
28
|
+
iconColor: "#6b7280",
|
|
29
|
+
};
|
|
30
|
+
export const defaultLabels = {
|
|
31
|
+
fr: {
|
|
32
|
+
photoTitle: (photoLabel) => `Photo ${photoLabel}`,
|
|
33
|
+
editAccessibilityLabel: (photoLabel) => `Photo ${photoLabel}. Modifier.`,
|
|
34
|
+
addAccessibilityLabel: (photoLabel) => `Ajouter une photo ${photoLabel}`,
|
|
35
|
+
addPlaceholderText: "Ajouter une photo",
|
|
36
|
+
cameraPermissionTitle: "Accès à l'appareil photo refusé",
|
|
37
|
+
cameraPermissionMessage: "Autorise l'accès dans les réglages du téléphone pour prendre une photo.",
|
|
38
|
+
takePhoto: "Prendre une photo",
|
|
39
|
+
chooseFromLibrary: "Choisir dans la galerie",
|
|
40
|
+
cancel: "Annuler",
|
|
41
|
+
removePhoto: "Retirer la photo",
|
|
42
|
+
saveErrorTitle: "Photo non enregistrée",
|
|
43
|
+
saveErrorMessage: "La photo n'a pas pu être enregistrée. Réessaie.",
|
|
44
|
+
},
|
|
45
|
+
en: {
|
|
46
|
+
photoTitle: (photoLabel) => `Photo ${photoLabel}`,
|
|
47
|
+
editAccessibilityLabel: (photoLabel) => `Photo ${photoLabel}. Edit.`,
|
|
48
|
+
addAccessibilityLabel: (photoLabel) => `Add a photo ${photoLabel}`,
|
|
49
|
+
addPlaceholderText: "Add a photo",
|
|
50
|
+
cameraPermissionTitle: "Camera access denied",
|
|
51
|
+
cameraPermissionMessage: "Allow access in the phone's settings to take a photo.",
|
|
52
|
+
takePhoto: "Take a photo",
|
|
53
|
+
chooseFromLibrary: "Choose from library",
|
|
54
|
+
cancel: "Cancel",
|
|
55
|
+
removePhoto: "Remove photo",
|
|
56
|
+
saveErrorTitle: "Photo not saved",
|
|
57
|
+
saveErrorMessage: "The photo could not be saved. Try again.",
|
|
58
|
+
},
|
|
59
|
+
};
|
|
@@ -1,24 +1,6 @@
|
|
|
1
|
-
import type { StyleProp, TextStyle, ViewStyle } from "react-native";
|
|
2
1
|
import { type KitLocale } from "../../i18n/locale.js";
|
|
3
|
-
|
|
4
|
-
export
|
|
5
|
-
/** The row: − button, field, + button. */
|
|
6
|
-
row?: StyleProp<ViewStyle>;
|
|
7
|
-
/** Both round buttons. */
|
|
8
|
-
button?: StyleProp<ViewStyle>;
|
|
9
|
-
/** Added on top of `button` for "−" at `min` and "+" at `max`. */
|
|
10
|
-
buttonDisabled?: StyleProp<ViewStyle>;
|
|
11
|
-
/** The "−" / "+" glyphs. */
|
|
12
|
-
buttonText?: StyleProp<TextStyle>;
|
|
13
|
-
/** The numeric field in the middle (its text color included). */
|
|
14
|
-
input?: StyleProp<TextStyle>;
|
|
15
|
-
}
|
|
16
|
-
/** Screen-reader labels of the three controls, built from the stepper's `label`. */
|
|
17
|
-
export interface QuantityStepperA11yLabels {
|
|
18
|
-
decrease: (label: string) => string;
|
|
19
|
-
increase: (label: string) => string;
|
|
20
|
-
input: (label: string) => string;
|
|
21
|
-
}
|
|
2
|
+
import { type QuantityStepperA11yLabels, type QuantityStepperStyles } from "./QuantityStepper.styles.js";
|
|
3
|
+
export type { QuantityStepperA11yLabels, QuantityStepperStyles, } from "./QuantityStepper.styles.js";
|
|
22
4
|
export interface QuantityStepperProps {
|
|
23
5
|
value: number;
|
|
24
6
|
/** Receives the new value, already clamped to `min…max`. */
|
|
@@ -27,12 +9,24 @@ export interface QuantityStepperProps {
|
|
|
27
9
|
label: string;
|
|
28
10
|
/**
|
|
29
11
|
* Below 0, negative values are allowed: the field then accepts a leading
|
|
30
|
-
* "-" (and opens the keyboard that has one).
|
|
12
|
+
* "-" (and opens the keyboard that has one). `-Infinity`: no lower bound.
|
|
31
13
|
* @defaultValue 0
|
|
32
14
|
*/
|
|
33
15
|
min?: number;
|
|
34
|
-
/** @defaultValue 999 */
|
|
16
|
+
/** `Infinity`: no upper bound. @defaultValue 999 */
|
|
35
17
|
max?: number;
|
|
18
|
+
/**
|
|
19
|
+
* How much −/+ (and each repeat while held) move the value, e.g. `4` for a
|
|
20
|
+
* category worth 4 points a unit. Typing in the field is not snapped to it.
|
|
21
|
+
* @defaultValue 1
|
|
22
|
+
*/
|
|
23
|
+
step?: number;
|
|
24
|
+
/**
|
|
25
|
+
* Called with the new value each time −/+ change it (tap, long press, each
|
|
26
|
+
* repeat while held) — not on typing. The place for a haptic tick:
|
|
27
|
+
* `onStep={tapFeedback}` (from `utils/helpers/haptics`).
|
|
28
|
+
*/
|
|
29
|
+
onStep?: (value: number) => void;
|
|
36
30
|
/**
|
|
37
31
|
* Step applied by a long press on −/+, to reach large values quickly.
|
|
38
32
|
* Unset, a long press does nothing more than a tap. Ignored with
|
|
@@ -45,6 +39,12 @@ export interface QuantityStepperProps {
|
|
|
45
39
|
* @defaultValue false
|
|
46
40
|
*/
|
|
47
41
|
repeatOnHold?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Caps how much the system font size scales the "−", "+" and the field, so
|
|
44
|
+
* the row keeps fitting at the largest accessibility font sizes (e.g. `1.3`).
|
|
45
|
+
* Unset, they follow the system font size without limit.
|
|
46
|
+
*/
|
|
47
|
+
maxFontSizeMultiplier?: number;
|
|
48
48
|
/**
|
|
49
49
|
* Language of the default screen-reader labels — French by default, or the
|
|
50
50
|
* nearest `KitLocaleProvider`'s.
|
|
@@ -56,13 +56,14 @@ export interface QuantityStepperProps {
|
|
|
56
56
|
styles?: QuantityStepperStyles;
|
|
57
57
|
}
|
|
58
58
|
/**
|
|
59
|
-
* A whole-number counter from `min` (0) to `max`: −/+ buttons to adjust
|
|
60
|
-
* (optionally faster on long press, or repeating while held), and a
|
|
61
|
-
* field in the middle to type a large number in one go (other
|
|
62
|
-
* dropped, the result is clamped). A typed value that is not a
|
|
63
|
-
* below `min` (an empty field, a lone "-", the "2" of "25" with
|
|
64
|
-
* stays as typed until the field loses focus. A negative `min`
|
|
65
|
-
* negative values (penalties, defeat tokens…)
|
|
59
|
+
* A whole-number counter from `min` (0) to `max`: −/+ buttons to adjust by
|
|
60
|
+
* `step` (optionally faster on long press, or repeating while held), and a
|
|
61
|
+
* numeric field in the middle to type a large number in one go (other
|
|
62
|
+
* characters are dropped, the result is clamped). A typed value that is not a
|
|
63
|
+
* number yet or below `min` (an empty field, a lone "-", the "2" of "25" with
|
|
64
|
+
* `min={10}`) stays as typed until the field loses focus. A negative `min`
|
|
65
|
+
* allows negative values (penalties, defeat tokens…); `-Infinity`/`Infinity`
|
|
66
|
+
* remove a bound.
|
|
66
67
|
*
|
|
67
68
|
* @example
|
|
68
69
|
* ```tsx
|
|
@@ -70,8 +71,8 @@ export interface QuantityStepperProps {
|
|
|
70
71
|
*
|
|
71
72
|
* <QuantityStepper value={count} onChange={setCount} label="Croissants" />
|
|
72
73
|
* <QuantityStepper value={bans} onChange={setBans} label="Bannissements" min={1} max={40} longPressStep={5} />
|
|
73
|
-
* <QuantityStepper value={score} onChange={setScore} label="Points" min={-
|
|
74
|
+
* <QuantityStepper value={score} onChange={setScore} label="Points" min={-Infinity} max={Infinity} step={4} repeatOnHold onStep={tapFeedback} />
|
|
74
75
|
* ```
|
|
75
76
|
*/
|
|
76
|
-
export declare function QuantityStepper({ value, onChange, label, min, max, longPressStep, repeatOnHold, locale, a11yLabels, styles, }: QuantityStepperProps): import("react").JSX.Element;
|
|
77
|
+
export declare function QuantityStepper({ value, onChange, label, min, max, step, onStep, longPressStep, repeatOnHold, maxFontSizeMultiplier, locale, a11yLabels, styles, }: QuantityStepperProps): import("react").JSX.Element;
|
|
77
78
|
//# sourceMappingURL=QuantityStepper.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QuantityStepper.d.ts","sourceRoot":"","sources":["../../../src/components/picker/QuantityStepper.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"QuantityStepper.d.ts","sourceRoot":"","sources":["../../../src/components/picker/QuantityStepper.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,SAAS,EAAgB,MAAM,sBAAsB,CAAC;AAGpE,OAAO,EAGL,KAAK,yBAAyB,EAC9B,KAAK,qBAAqB,EAC3B,MAAM,6BAA6B,CAAC;AAErC,YAAY,EACV,yBAAyB,EACzB,qBAAqB,GACtB,MAAM,6BAA6B,CAAC;AAErC,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,gEAAgE;IAChE,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B;;;OAGG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,yDAAyD;IACzD,UAAU,CAAC,EAAE,OAAO,CAAC,yBAAyB,CAAC,CAAC;IAChD,oEAAoE;IACpE,MAAM,CAAC,EAAE,qBAAqB,CAAC;CAChC;AAgBD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,QAAQ,EACR,KAAK,EACL,GAAO,EACP,GAAS,EACT,IAAQ,EACR,MAAM,EACN,aAAa,EACb,YAAoB,EACpB,qBAAqB,EACrB,MAAM,EACN,UAAU,EACV,MAAM,GACP,EAAE,oBAAoB,+BAuJtB"}
|