@colixsystems/widget-sdk 0.210.0 → 0.213.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 +100 -2
- package/dist/button-view.js +5 -3
- package/dist/checkbox-view.js +150 -0
- package/dist/checkbox.js +11 -0
- package/dist/checkbox.native.js +7 -0
- package/dist/confirm-dialog-view.js +158 -0
- package/dist/confirm-dialog.js +11 -0
- package/dist/confirm-dialog.native.js +11 -0
- package/dist/contract.cjs +54 -3
- package/dist/contract.js +54 -3
- package/dist/form-control-logic.js +55 -0
- package/dist/form-control-tokens.js +121 -0
- package/dist/form-control-view.js +98 -0
- package/dist/index.d.ts +202 -6
- package/dist/index.js +11 -1
- package/dist/index.native.js +11 -1
- package/dist/search-field-view.js +155 -0
- package/dist/search-field.js +13 -0
- package/dist/search-field.native.js +9 -0
- package/dist/select-view.js +312 -0
- package/dist/select.js +15 -0
- package/dist/select.native.js +9 -0
- package/dist/switch-view.js +149 -0
- package/dist/switch.js +80 -0
- package/dist/switch.native.js +7 -0
- package/dist/text-field-view.js +54 -8
- package/dist/text-field.js +6 -1
- package/dist/text-field.native.js +3 -3
- package/package.json +1 -1
- package/src/contract.js +54 -3
package/dist/index.d.ts
CHANGED
|
@@ -3167,7 +3167,6 @@ export const TextInput: any;
|
|
|
3167
3167
|
export const FlatList: any;
|
|
3168
3168
|
export const SectionList: any;
|
|
3169
3169
|
export const ActivityIndicator: any;
|
|
3170
|
-
export const Switch: any;
|
|
3171
3170
|
export const StyleSheet: any;
|
|
3172
3171
|
|
|
3173
3172
|
/**
|
|
@@ -3361,6 +3360,70 @@ export const Modal: (props: {
|
|
|
3361
3360
|
children?: ReactNode;
|
|
3362
3361
|
}) => any;
|
|
3363
3362
|
|
|
3363
|
+
export type ConfirmDialogTone = "default" | "destructive";
|
|
3364
|
+
|
|
3365
|
+
/**
|
|
3366
|
+
* The standard confirmation prompt: a preset of `<Modal>` with a message, a
|
|
3367
|
+
* Cancel and a Confirm `<Button>`. Use it before a delete or any other action
|
|
3368
|
+
* that cannot be undone, so every confirmation in the app looks and behaves
|
|
3369
|
+
* the same. Cancelling is the safe default: the Cancel button, the close
|
|
3370
|
+
* button, the backdrop, Escape (web) and the Android back button all fire
|
|
3371
|
+
* `onCancel`, never `onConfirm`.
|
|
3372
|
+
*
|
|
3373
|
+
* It adds no theme scope: the panel follows `modal`, the actions `button`,
|
|
3374
|
+
* and a destructive confirm the `destructive` scope. It never closes itself;
|
|
3375
|
+
* set `visible` false from `onCancel` and once the action is done.
|
|
3376
|
+
*
|
|
3377
|
+
* @example
|
|
3378
|
+
* <ConfirmDialog
|
|
3379
|
+
* visible={!!pending}
|
|
3380
|
+
* tone="destructive"
|
|
3381
|
+
* title="Delete this order?"
|
|
3382
|
+
* message="This cannot be undone."
|
|
3383
|
+
* confirmLabel="Delete"
|
|
3384
|
+
* onCancel={() => setPending(null)}
|
|
3385
|
+
* onConfirm={async () => {
|
|
3386
|
+
* await remove(pending.id);
|
|
3387
|
+
* setPending(null);
|
|
3388
|
+
* }}
|
|
3389
|
+
* />
|
|
3390
|
+
*/
|
|
3391
|
+
export const ConfirmDialog: (props: {
|
|
3392
|
+
/** Nothing renders (and nothing is mounted) while this is false. */
|
|
3393
|
+
visible?: boolean;
|
|
3394
|
+
/** The question, e.g. "Delete this order?". */
|
|
3395
|
+
title: string;
|
|
3396
|
+
/** What confirming does. Text is drawn in the theme's body style. */
|
|
3397
|
+
message?: ReactNode;
|
|
3398
|
+
/** Defaults to the app's translated "Confirm". Name the action instead. */
|
|
3399
|
+
confirmLabel?: string;
|
|
3400
|
+
/** Defaults to the app's translated "Cancel". */
|
|
3401
|
+
cancelLabel?: string;
|
|
3402
|
+
/**
|
|
3403
|
+
* `destructive` draws the confirm button from the theme's Destructive
|
|
3404
|
+
* colours and, on web, opens with focus on Cancel. `default` opens with
|
|
3405
|
+
* focus on Confirm. Focus placement is web only.
|
|
3406
|
+
*/
|
|
3407
|
+
tone?: ConfirmDialogTone;
|
|
3408
|
+
/**
|
|
3409
|
+
* The confirmed action is running: both buttons are disabled, a loading
|
|
3410
|
+
* indicator shows, and the backdrop, Escape and Android back do nothing.
|
|
3411
|
+
*/
|
|
3412
|
+
busy?: boolean;
|
|
3413
|
+
/**
|
|
3414
|
+
* Return the action's promise and the dialog stays busy until it settles,
|
|
3415
|
+
* ignoring a second press. A rejection is not caught: handle the failure
|
|
3416
|
+
* here, or it is reported as an unhandled rejection.
|
|
3417
|
+
*/
|
|
3418
|
+
onConfirm?: () => void | Promise<unknown>;
|
|
3419
|
+
/** The Cancel and close buttons, backdrop, Escape (web) and Android back. */
|
|
3420
|
+
onCancel?: () => void;
|
|
3421
|
+
/** Label for the close button. Defaults to the app's translated "Close". */
|
|
3422
|
+
closeAccessibilityLabel?: string;
|
|
3423
|
+
/** On the panel; the parts take `-message`, `-cancel`, `-confirm` and `-busy`. */
|
|
3424
|
+
testID?: string;
|
|
3425
|
+
}) => any;
|
|
3426
|
+
|
|
3364
3427
|
/** Per-list row overrides; unset values follow Theme Settings > Lists. */
|
|
3365
3428
|
export interface ListRowTokens {
|
|
3366
3429
|
rowPadding?: number;
|
|
@@ -3617,22 +3680,155 @@ export const Button: (props: {
|
|
|
3617
3680
|
labelStyle?: any;
|
|
3618
3681
|
accessibilityLabel?: string;
|
|
3619
3682
|
testID?: string;
|
|
3683
|
+
/** Forwarded to the pressable, so you can focus the button. */
|
|
3684
|
+
ref?: { current: any } | ((node: any) => void);
|
|
3620
3685
|
}) => any;
|
|
3621
3686
|
|
|
3622
3687
|
/**
|
|
3623
|
-
*
|
|
3624
|
-
*
|
|
3625
|
-
*
|
|
3626
|
-
* <TextField value={name} onChangeText={setName} placeholder="Your name" accessibilityLabel="Name" />
|
|
3688
|
+
* What every form control shares: the label drawn with it (and read by a
|
|
3689
|
+
* screen reader), a hint below it, and an error that replaces the hint and
|
|
3690
|
+
* marks the control. `error: true` marks it without a message.
|
|
3627
3691
|
*/
|
|
3628
|
-
export
|
|
3692
|
+
export interface FormControlProps {
|
|
3693
|
+
label?: ReactNode;
|
|
3694
|
+
helper?: ReactNode;
|
|
3695
|
+
error?: ReactNode | boolean;
|
|
3696
|
+
disabled?: boolean;
|
|
3697
|
+
/** Required when there is no text `label`. */
|
|
3698
|
+
accessibilityLabel?: string;
|
|
3699
|
+
testID?: string;
|
|
3700
|
+
}
|
|
3701
|
+
|
|
3702
|
+
/** Per-control overrides of the theme's `muted` scope. */
|
|
3703
|
+
export interface FormFieldOverrides {
|
|
3629
3704
|
background?: string;
|
|
3630
3705
|
textColor?: string;
|
|
3631
3706
|
borderColor?: string;
|
|
3632
3707
|
radius?: number;
|
|
3633
3708
|
height?: number;
|
|
3709
|
+
}
|
|
3710
|
+
|
|
3711
|
+
/**
|
|
3712
|
+
* Themed text-entry field (Design > Components > Muted). Every TextInput prop
|
|
3713
|
+
* works.
|
|
3714
|
+
*
|
|
3715
|
+
* @example
|
|
3716
|
+
* <TextField label="Name" value={name} onChangeText={setName} placeholder="Your name" />
|
|
3717
|
+
*/
|
|
3718
|
+
export const TextField: (props: FormControlProps & FormFieldOverrides & {
|
|
3634
3719
|
multiline?: boolean;
|
|
3635
3720
|
style?: any;
|
|
3721
|
+
/** The box around a labelled field. */
|
|
3722
|
+
containerStyle?: any;
|
|
3723
|
+
[prop: string]: any;
|
|
3724
|
+
}) => any;
|
|
3725
|
+
|
|
3726
|
+
/**
|
|
3727
|
+
* Themed tick box: the input surface, filled with the primary colour when
|
|
3728
|
+
* checked. One 44px target with the checkbox role and state on both hosts.
|
|
3729
|
+
*
|
|
3730
|
+
* @example
|
|
3731
|
+
* <Checkbox label="Remember me" value={remember} onValueChange={setRemember} />
|
|
3732
|
+
*/
|
|
3733
|
+
export const Checkbox: (props: FormControlProps & {
|
|
3734
|
+
value?: boolean;
|
|
3735
|
+
onValueChange?: (next: boolean) => void;
|
|
3736
|
+
/** The row. */
|
|
3737
|
+
style?: any;
|
|
3738
|
+
/** The box around a row that shows a helper or an error. */
|
|
3739
|
+
containerStyle?: any;
|
|
3740
|
+
[prop: string]: any;
|
|
3741
|
+
}) => any;
|
|
3742
|
+
|
|
3743
|
+
/**
|
|
3744
|
+
* Themed on/off toggle: the platform's own switch with the theme's track
|
|
3745
|
+
* colours. Every React Native `Switch` prop works: a `trackColor` overrides
|
|
3746
|
+
* the theme for the states it names, and the thumb is the platform's unless
|
|
3747
|
+
* `thumbColor` is passed. Without a label, helper or error it renders the
|
|
3748
|
+
* bare switch.
|
|
3749
|
+
*
|
|
3750
|
+
* @example
|
|
3751
|
+
* <Switch label="Email me updates" value={on} onValueChange={setOn} />
|
|
3752
|
+
*/
|
|
3753
|
+
export const Switch: (props: FormControlProps & {
|
|
3754
|
+
value?: boolean;
|
|
3755
|
+
onValueChange?: (next: boolean) => void;
|
|
3756
|
+
trackColor?: { false?: string; true?: string };
|
|
3757
|
+
thumbColor?: string;
|
|
3758
|
+
style?: any;
|
|
3759
|
+
/** The box around a labelled switch. */
|
|
3760
|
+
containerStyle?: any;
|
|
3761
|
+
[prop: string]: any;
|
|
3762
|
+
}) => any;
|
|
3763
|
+
|
|
3764
|
+
export interface SelectOption<V extends string | number = string | number> {
|
|
3765
|
+
value: V;
|
|
3766
|
+
label: string;
|
|
3767
|
+
disabled?: boolean;
|
|
3768
|
+
testID?: string;
|
|
3769
|
+
}
|
|
3770
|
+
|
|
3771
|
+
/**
|
|
3772
|
+
* Themed single-choice picker. The trigger is the input field, a button that
|
|
3773
|
+
* opens a dialog; its options open at screen level (through `Overlay`) in a
|
|
3774
|
+
* sheet painted from the `popover` scope, so no container clips them and a
|
|
3775
|
+
* long list scrolls. Each option has the option role; the list is a listbox
|
|
3776
|
+
* on the web only. Other props land on the trigger.
|
|
3777
|
+
*
|
|
3778
|
+
* @example
|
|
3779
|
+
* <Select label="Status" value={status} onValueChange={setStatus}
|
|
3780
|
+
* options={[{ value: "open", label: "Open" }, { value: "done", label: "Done" }]} />
|
|
3781
|
+
*/
|
|
3782
|
+
export const Select: <V extends string | number = string | number>(
|
|
3783
|
+
props: FormControlProps & FormFieldOverrides & {
|
|
3784
|
+
options: Array<SelectOption<V>>;
|
|
3785
|
+
value?: V | null;
|
|
3786
|
+
onValueChange?: (value: V, option: SelectOption<V>) => void;
|
|
3787
|
+
/** Shown while nothing is chosen. Default "Select". */
|
|
3788
|
+
placeholder?: string;
|
|
3789
|
+
/** The sheet's heading. Defaults to a text `label`. */
|
|
3790
|
+
title?: string;
|
|
3791
|
+
/** Shown in the sheet when `options` is empty. Default "No options". */
|
|
3792
|
+
emptyText?: string;
|
|
3793
|
+
closeAccessibilityLabel?: string;
|
|
3794
|
+
/** The trigger. */
|
|
3795
|
+
style?: any;
|
|
3796
|
+
containerStyle?: any;
|
|
3797
|
+
[prop: string]: any;
|
|
3798
|
+
},
|
|
3799
|
+
) => any;
|
|
3800
|
+
|
|
3801
|
+
/**
|
|
3802
|
+
* Space-key activation for a control whose role is not a button: on the web a
|
|
3803
|
+
* `Pressable` answers Space only for a button. Native ignores `onKeyDown`.
|
|
3804
|
+
*
|
|
3805
|
+
* @example
|
|
3806
|
+
* <Pressable accessibilityRole="radio" onPress={pick} onKeyDown={spaceActivates(pick)} />
|
|
3807
|
+
*/
|
|
3808
|
+
export function spaceActivates(
|
|
3809
|
+
onPress: () => void,
|
|
3810
|
+
): (event: { key: string; repeat?: boolean; preventDefault: () => void }) => void;
|
|
3811
|
+
|
|
3812
|
+
/**
|
|
3813
|
+
* Themed search box: a `TextField` with a search glyph, the search key and a
|
|
3814
|
+
* clear control. Every `TextField` prop works.
|
|
3815
|
+
*
|
|
3816
|
+
* @example
|
|
3817
|
+
* <SearchField value={query} onChangeText={setQuery} placeholder="Search orders" />
|
|
3818
|
+
*/
|
|
3819
|
+
export const SearchField: (props: FormControlProps & {
|
|
3820
|
+
value?: string;
|
|
3821
|
+
onChangeText?: (text: string) => void;
|
|
3822
|
+
/** Called after the clear control empties the field. */
|
|
3823
|
+
onClear?: () => void;
|
|
3824
|
+
/** Default "Search". */
|
|
3825
|
+
placeholder?: string;
|
|
3826
|
+
/** Default "Clear search". */
|
|
3827
|
+
clearAccessibilityLabel?: string;
|
|
3828
|
+
/** The input. */
|
|
3829
|
+
style?: any;
|
|
3830
|
+
/** The box around it; use it for `flex: 1` in a toolbar. */
|
|
3831
|
+
containerStyle?: any;
|
|
3636
3832
|
[prop: string]: any;
|
|
3637
3833
|
}) => any;
|
|
3638
3834
|
|
package/dist/index.js
CHANGED
|
@@ -167,7 +167,6 @@ export {
|
|
|
167
167
|
FlatList,
|
|
168
168
|
SectionList,
|
|
169
169
|
ActivityIndicator,
|
|
170
|
-
Switch,
|
|
171
170
|
StyleSheet,
|
|
172
171
|
Linking,
|
|
173
172
|
Icon,
|
|
@@ -266,6 +265,15 @@ export {
|
|
|
266
265
|
export { TextField } from "./text-field.js";
|
|
267
266
|
// Themed collapsible sections, drawn from the `card` and `list` scopes.
|
|
268
267
|
export { Accordion, AccordionItem } from "./accordion.js";
|
|
268
|
+
// The themed form controls; they follow the theme's `muted` scope as
|
|
269
|
+
// `<TextField>` does, and `popover` for the Select's options. `<Switch>` is
|
|
270
|
+
// the platform's own.
|
|
271
|
+
export { Checkbox } from "./checkbox.js";
|
|
272
|
+
export { Switch } from "./switch.js";
|
|
273
|
+
export { Select } from "./select.js";
|
|
274
|
+
export { SearchField } from "./search-field.js";
|
|
275
|
+
// Space for a control whose role is not a button; a no-op on native.
|
|
276
|
+
export { spaceActivates } from "./form-control-logic.js";
|
|
269
277
|
// A themed tab strip; follows the theme's `tabs` scope.
|
|
270
278
|
export { Tabs } from "./tabs.js";
|
|
271
279
|
// Themed loading states; follow the theme's `loading` scope.
|
|
@@ -274,6 +282,8 @@ export { Spinner, Skeleton } from "./loading.js";
|
|
|
274
282
|
export { Banner } from "./banner.js";
|
|
275
283
|
// The standard dialog, on `<Overlay>`; follows the theme's `modal` scope.
|
|
276
284
|
export { Modal } from "./modal.js";
|
|
285
|
+
// The standard confirmation, a preset of `<Modal>` and `<Button>`.
|
|
286
|
+
export { ConfirmDialog } from "./confirm-dialog.js";
|
|
277
287
|
// The semantic text tiers, shared with the built-in widgets.
|
|
278
288
|
export {
|
|
279
289
|
textRoleStyle,
|
package/dist/index.native.js
CHANGED
|
@@ -160,7 +160,6 @@ export {
|
|
|
160
160
|
FlatList,
|
|
161
161
|
SectionList,
|
|
162
162
|
ActivityIndicator,
|
|
163
|
-
Switch,
|
|
164
163
|
StyleSheet,
|
|
165
164
|
Linking,
|
|
166
165
|
Icon,
|
|
@@ -259,6 +258,15 @@ export {
|
|
|
259
258
|
export { TextField } from "./text-field.native.js";
|
|
260
259
|
// Themed collapsible sections, drawn from the `card` and `list` scopes.
|
|
261
260
|
export { Accordion, AccordionItem } from "./accordion.native.js";
|
|
261
|
+
// The themed form controls; they follow the theme's `muted` scope as
|
|
262
|
+
// `<TextField>` does, and `popover` for the Select's options. `<Switch>` is
|
|
263
|
+
// the platform's own.
|
|
264
|
+
export { Checkbox } from "./checkbox.native.js";
|
|
265
|
+
export { Switch } from "./switch.native.js";
|
|
266
|
+
export { Select } from "./select.native.js";
|
|
267
|
+
export { SearchField } from "./search-field.native.js";
|
|
268
|
+
// Space for a control whose role is not a button; a no-op on native.
|
|
269
|
+
export { spaceActivates } from "./form-control-logic.js";
|
|
262
270
|
// A themed tab strip; follows the theme's `tabs` scope.
|
|
263
271
|
export { Tabs } from "./tabs.native.js";
|
|
264
272
|
// Themed loading states; follow the theme's `loading` scope.
|
|
@@ -267,6 +275,8 @@ export { Spinner, Skeleton } from "./loading.native.js";
|
|
|
267
275
|
export { Banner } from "./banner.native.js";
|
|
268
276
|
// The standard dialog, on `<Overlay>`; follows the theme's `modal` scope.
|
|
269
277
|
export { Modal } from "./modal.native.js";
|
|
278
|
+
// The standard confirmation, a preset of `<Modal>` and `<Button>`.
|
|
279
|
+
export { ConfirmDialog } from "./confirm-dialog.native.js";
|
|
270
280
|
// The semantic text tiers, shared with the built-in widgets.
|
|
271
281
|
export {
|
|
272
282
|
textRoleStyle,
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
// The ONE implementation behind the `<SearchField>` SDK primitive. It is
|
|
2
|
+
// `<TextField>` with a search glyph and a clear control, so it wears the same
|
|
3
|
+
// field and takes the same props; the platform bindings (`search-field.js` /
|
|
4
|
+
// `search-field.native.js`) differ only in where the primitives come from.
|
|
5
|
+
|
|
6
|
+
import React from "react";
|
|
7
|
+
import { useHostTheme } from "./hooks.js";
|
|
8
|
+
import { DEFAULT_THEME_TOKENS } from "./_theme-tokens.js";
|
|
9
|
+
import { Icon } from "./icon.js";
|
|
10
|
+
import { resolveFormControlTokens } from "./form-control-tokens.js";
|
|
11
|
+
import {
|
|
12
|
+
errorMessage,
|
|
13
|
+
hasNote,
|
|
14
|
+
isShown,
|
|
15
|
+
shareRef,
|
|
16
|
+
spokenLabel,
|
|
17
|
+
} from "./form-control-logic.js";
|
|
18
|
+
import { makeFieldFrame } from "./form-control-view.js";
|
|
19
|
+
|
|
20
|
+
const h = React.createElement;
|
|
21
|
+
const GLYPH_SIZE = 18;
|
|
22
|
+
// The glyph and the clear control each own a strip this wide inside the field.
|
|
23
|
+
const ADORNMENT_WIDTH = 40;
|
|
24
|
+
// A real target: the web host ignores hitSlop, so size carries it.
|
|
25
|
+
const CLEAR_MIN_SIZE = 36;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Bind the shared search field to one platform's primitives.
|
|
29
|
+
*
|
|
30
|
+
* @param {{View: any, Text: any, Pressable: any, TextField: any}} rn
|
|
31
|
+
*/
|
|
32
|
+
export function makeSearchField(rn) {
|
|
33
|
+
const { View, Pressable, TextField } = rn;
|
|
34
|
+
const FieldFrame = makeFieldFrame(rn);
|
|
35
|
+
|
|
36
|
+
const SearchField = React.forwardRef(function SearchField(props, ref) {
|
|
37
|
+
const {
|
|
38
|
+
value,
|
|
39
|
+
onChangeText,
|
|
40
|
+
onClear,
|
|
41
|
+
placeholder = "Search",
|
|
42
|
+
clearAccessibilityLabel = "Clear search",
|
|
43
|
+
label,
|
|
44
|
+
helper,
|
|
45
|
+
error,
|
|
46
|
+
disabled = false,
|
|
47
|
+
accessibilityLabel,
|
|
48
|
+
style,
|
|
49
|
+
containerStyle,
|
|
50
|
+
testID,
|
|
51
|
+
...rest
|
|
52
|
+
} = props;
|
|
53
|
+
const theme = useHostTheme() || DEFAULT_THEME_TOKENS;
|
|
54
|
+
const t = resolveFormControlTokens(theme);
|
|
55
|
+
const inputRef = React.useRef(null);
|
|
56
|
+
const setRef = React.useMemo(() => shareRef(ref, inputRef), [ref]);
|
|
57
|
+
const noteId = React.useId();
|
|
58
|
+
const focusInput = () => {
|
|
59
|
+
const input = inputRef.current;
|
|
60
|
+
if (input && typeof input.focus === "function") input.focus();
|
|
61
|
+
};
|
|
62
|
+
const hasText = typeof value === "string" && value.length > 0;
|
|
63
|
+
const clear = () => {
|
|
64
|
+
if (typeof onChangeText === "function") onChangeText("");
|
|
65
|
+
if (typeof onClear === "function") onClear();
|
|
66
|
+
focusInput();
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
return h(
|
|
70
|
+
FieldFrame,
|
|
71
|
+
{
|
|
72
|
+
t,
|
|
73
|
+
label,
|
|
74
|
+
helper,
|
|
75
|
+
error: errorMessage(error),
|
|
76
|
+
disabled,
|
|
77
|
+
noteId,
|
|
78
|
+
onLabelPress: focusInput,
|
|
79
|
+
style: containerStyle,
|
|
80
|
+
},
|
|
81
|
+
h(
|
|
82
|
+
View,
|
|
83
|
+
{ style: { justifyContent: "center" } },
|
|
84
|
+
h(TextField, {
|
|
85
|
+
ref: setRef,
|
|
86
|
+
value,
|
|
87
|
+
onChangeText,
|
|
88
|
+
placeholder,
|
|
89
|
+
// The frame dims the whole control, glyph included.
|
|
90
|
+
...(disabled ? { editable: false, "aria-disabled": true } : null),
|
|
91
|
+
error: isShown(error),
|
|
92
|
+
...(hasNote({ helper, error }) ? { "aria-describedby": noteId } : null),
|
|
93
|
+
// `role` names it on the web; `accessibilityRole` on a device.
|
|
94
|
+
role: "searchbox",
|
|
95
|
+
accessibilityRole: "search",
|
|
96
|
+
accessibilityLabel: spokenLabel(accessibilityLabel, label) || placeholder,
|
|
97
|
+
enterKeyHint: "search",
|
|
98
|
+
autoCapitalize: "none",
|
|
99
|
+
autoCorrect: false,
|
|
100
|
+
testID,
|
|
101
|
+
...rest,
|
|
102
|
+
style: [
|
|
103
|
+
{ paddingLeft: ADORNMENT_WIDTH },
|
|
104
|
+
hasText && !disabled ? { paddingRight: ADORNMENT_WIDTH } : null,
|
|
105
|
+
style,
|
|
106
|
+
],
|
|
107
|
+
}),
|
|
108
|
+
h(
|
|
109
|
+
View,
|
|
110
|
+
{
|
|
111
|
+
style: {
|
|
112
|
+
position: "absolute",
|
|
113
|
+
left: 0,
|
|
114
|
+
top: 0,
|
|
115
|
+
bottom: 0,
|
|
116
|
+
width: ADORNMENT_WIDTH,
|
|
117
|
+
alignItems: "center",
|
|
118
|
+
justifyContent: "center",
|
|
119
|
+
pointerEvents: "none",
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
h(Icon, { name: "search", size: GLYPH_SIZE, color: t.placeholderColor }),
|
|
123
|
+
),
|
|
124
|
+
hasText && !disabled
|
|
125
|
+
? h(
|
|
126
|
+
Pressable,
|
|
127
|
+
{
|
|
128
|
+
onPress: clear,
|
|
129
|
+
accessibilityRole: "button",
|
|
130
|
+
accessibilityLabel: clearAccessibilityLabel,
|
|
131
|
+
testID: testID ? `${testID}-clear` : undefined,
|
|
132
|
+
style: ({ pressed }) => [
|
|
133
|
+
{
|
|
134
|
+
position: "absolute",
|
|
135
|
+
right: 2,
|
|
136
|
+
top: 0,
|
|
137
|
+
bottom: 0,
|
|
138
|
+
minWidth: CLEAR_MIN_SIZE,
|
|
139
|
+
minHeight: CLEAR_MIN_SIZE,
|
|
140
|
+
alignItems: "center",
|
|
141
|
+
justifyContent: "center",
|
|
142
|
+
},
|
|
143
|
+
pressed ? { opacity: 0.6 } : null,
|
|
144
|
+
],
|
|
145
|
+
},
|
|
146
|
+
h(Icon, { name: "x", size: GLYPH_SIZE, color: t.placeholderColor }),
|
|
147
|
+
)
|
|
148
|
+
: null,
|
|
149
|
+
),
|
|
150
|
+
);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
SearchField.displayName = "SearchField";
|
|
154
|
+
return SearchField;
|
|
155
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// `<SearchField>` (web). Binds ./search-field-view.js to react-native-web and
|
|
2
|
+
// the web `<TextField>`; see ./primitives.js for why not the bare specifier.
|
|
3
|
+
|
|
4
|
+
import * as ReactNative from "react-native-web";
|
|
5
|
+
import { makeSearchField } from "./search-field-view.js";
|
|
6
|
+
import { TextField } from "./text-field.js";
|
|
7
|
+
|
|
8
|
+
export const SearchField = makeSearchField({
|
|
9
|
+
View: ReactNative.View,
|
|
10
|
+
Text: ReactNative.Text,
|
|
11
|
+
Pressable: ReactNative.Pressable,
|
|
12
|
+
TextField,
|
|
13
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// `<SearchField>` (native). Binds ./search-field-view.js to React Native's own
|
|
2
|
+
// primitives and the native `<TextField>`; only the imports differ from
|
|
3
|
+
// ./search-field.js.
|
|
4
|
+
|
|
5
|
+
import { View, Text, Pressable } from "react-native";
|
|
6
|
+
import { makeSearchField } from "./search-field-view.js";
|
|
7
|
+
import { TextField } from "./text-field.native.js";
|
|
8
|
+
|
|
9
|
+
export const SearchField = makeSearchField({ View, Text, Pressable, TextField });
|