@colixsystems/widget-sdk 0.236.0 → 0.238.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 +29 -4
- package/dist/checkbox-view.js +28 -16
- package/dist/contract.cjs +57 -24
- package/dist/contract.js +57 -24
- package/dist/file-upload-logic.js +178 -0
- package/dist/file-upload-view.js +321 -0
- package/dist/file-upload.js +62 -0
- package/dist/file-upload.native.js +11 -0
- package/dist/filepicker.js +11 -0
- package/dist/filepicker.native.js +10 -1
- package/dist/form-control-view.js +8 -1
- package/dist/host.d.ts +6 -0
- package/dist/host.js +2 -0
- package/dist/index.d.ts +168 -19
- package/dist/index.js +2 -0
- package/dist/index.native.js +2 -0
- package/dist/list-tokens.js +54 -14
- package/dist/list-view.js +199 -82
- package/dist/list.js +7 -1
- package/dist/list.native.js +3 -2
- package/dist/primitives.js +1 -3
- package/dist/primitives.native.js +2 -4
- package/dist/search-field-tokens.js +85 -0
- package/dist/search-field-view.js +39 -26
- package/dist/select-logic.js +83 -0
- package/dist/select-view.js +165 -32
- package/dist/select.js +6 -1
- package/dist/select.native.js +5 -3
- package/package.json +1 -1
- package/src/contract.js +57 -24
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// The `<Select>` rules that need no renderer: where focus lands when the
|
|
2
|
+
// sheet opens, the draft a `multiple` select edits until Done, and what its
|
|
3
|
+
// trigger shows. Both hosts share them, and the node suite tests them.
|
|
4
|
+
|
|
5
|
+
/** The default trigger text once the picked labels no longer fit. */
|
|
6
|
+
export function defaultSelectedCountText(count) {
|
|
7
|
+
return `${count} selected`;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/** A `values` prop as a list; anything else is no choice. */
|
|
11
|
+
export function valueList(values) {
|
|
12
|
+
return Array.isArray(values) ? values : [];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* The option focused when the sheet opens: the first picked one that can be
|
|
17
|
+
* picked, else the first enabled one, else -1.
|
|
18
|
+
*
|
|
19
|
+
* @param {Array<{disabled?: boolean}>} options
|
|
20
|
+
* @param {(option: object) => boolean} isPicked
|
|
21
|
+
*/
|
|
22
|
+
export function initialFocusIndex(options, isPicked) {
|
|
23
|
+
const list = Array.isArray(options) ? options : [];
|
|
24
|
+
const picked = list.findIndex((option) => isPicked(option) && !option.disabled);
|
|
25
|
+
return picked !== -1 ? picked : list.findIndex((option) => !option.disabled);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The draft with `value` added, or removed when it is already in it. Values
|
|
30
|
+
* compare strictly, so 1 and "1" are two choices.
|
|
31
|
+
*
|
|
32
|
+
* @param {Array<string|number>} draft
|
|
33
|
+
* @param {string|number} value
|
|
34
|
+
*/
|
|
35
|
+
export function toggleValue(draft, value) {
|
|
36
|
+
const list = valueList(draft);
|
|
37
|
+
return list.includes(value) ? list.filter((own) => own !== value) : [...list, value];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The values Done reports: the picked options in the order they are listed,
|
|
42
|
+
* then any picked value no option carries any more, so confirming without a
|
|
43
|
+
* change never drops a stored value.
|
|
44
|
+
*
|
|
45
|
+
* @param {Array<{value: string|number}>} options
|
|
46
|
+
* @param {Array<string|number>} draft
|
|
47
|
+
*/
|
|
48
|
+
export function committedValues(options, draft) {
|
|
49
|
+
const list = valueList(draft);
|
|
50
|
+
const known = (Array.isArray(options) ? options : []).map((option) => option.value);
|
|
51
|
+
return [
|
|
52
|
+
...known.filter((value) => list.includes(value)),
|
|
53
|
+
...list.filter((value) => !known.includes(value)),
|
|
54
|
+
];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Whether two value lists hold the same values, whatever their order. */
|
|
58
|
+
export function sameValues(a, b) {
|
|
59
|
+
const left = valueList(a);
|
|
60
|
+
const right = valueList(b);
|
|
61
|
+
return left.length === right.length && left.every((value) => right.includes(value));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** The options whose value is picked, in the order they are listed. */
|
|
65
|
+
export function pickedOptions(options, values) {
|
|
66
|
+
const list = valueList(values);
|
|
67
|
+
return (Array.isArray(options) ? options : []).filter((option) => list.includes(option.value));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* What a `multiple` trigger shows: the placeholder with nothing picked, the
|
|
72
|
+
* picked labels as chips once they are measured to fit on its one line,
|
|
73
|
+
* otherwise the count. Until both widths are known it shows the count, so
|
|
74
|
+
* the trigger never draws chips that overflow it.
|
|
75
|
+
*
|
|
76
|
+
* @param {{picked: number, available?: number|null, needed?: number|null}} sizes
|
|
77
|
+
* @returns {"placeholder"|"chips"|"count"}
|
|
78
|
+
*/
|
|
79
|
+
export function triggerSummary({ picked, available, needed }) {
|
|
80
|
+
if (!picked) return "placeholder";
|
|
81
|
+
const measured = Number.isFinite(available) && Number.isFinite(needed) && available > 0;
|
|
82
|
+
return measured && needed <= available ? "chips" : "count";
|
|
83
|
+
}
|
package/dist/select-view.js
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
//
|
|
5
5
|
// The trigger wears the field `<TextField>` does. The options open in
|
|
6
6
|
// `<Overlay>`, at screen level, so no card or scroll container the widget
|
|
7
|
-
// sits in can clip them; a long list scrolls inside the sheet.
|
|
7
|
+
// sits in can clip them; a long list scrolls inside the sheet. With
|
|
8
|
+
// `multiple` the same sheet ticks options into a draft that Done commits.
|
|
8
9
|
|
|
9
10
|
import React from "react";
|
|
10
11
|
import { useHostTheme } from "./hooks.js";
|
|
@@ -29,17 +30,34 @@ import {
|
|
|
29
30
|
spokenLabel,
|
|
30
31
|
} from "./form-control-logic.js";
|
|
31
32
|
import { makeFieldFrame } from "./form-control-view.js";
|
|
33
|
+
import { checkboxBox } from "./checkbox-view.js";
|
|
34
|
+
import {
|
|
35
|
+
committedValues,
|
|
36
|
+
defaultSelectedCountText,
|
|
37
|
+
initialFocusIndex,
|
|
38
|
+
pickedOptions,
|
|
39
|
+
sameValues,
|
|
40
|
+
toggleValue,
|
|
41
|
+
triggerSummary,
|
|
42
|
+
valueList,
|
|
43
|
+
} from "./select-logic.js";
|
|
32
44
|
|
|
33
45
|
const h = React.createElement;
|
|
34
46
|
const NAVIGATION_KEYS = ["ArrowDown", "ArrowUp", "Home", "End"];
|
|
47
|
+
// Wide enough that no picked chip shrinks while it is measured.
|
|
48
|
+
const MEASURE_SPAN = 10000;
|
|
49
|
+
// A compact chip that fits the field's own line, so the trigger keeps its height.
|
|
50
|
+
const TRIGGER_CHIP_STYLE = Object.freeze({ minHeight: 0, paddingVertical: 2 });
|
|
51
|
+
const UNMEASURED = Object.freeze({ available: null, needed: null });
|
|
35
52
|
|
|
36
53
|
/**
|
|
37
54
|
* Bind the shared select to one platform's primitives.
|
|
38
55
|
*
|
|
39
|
-
* @param {{View: any, Text: any, Pressable: any, ScrollView: any, Platform: any,
|
|
56
|
+
* @param {{View: any, Text: any, Pressable: any, ScrollView: any, Platform: any,
|
|
57
|
+
* Overlay: any, Button: any, Chip: any}} rn
|
|
40
58
|
*/
|
|
41
59
|
export function makeSelect(rn) {
|
|
42
|
-
const { View, Text, Pressable, ScrollView, Platform, Overlay } = rn;
|
|
60
|
+
const { View, Text, Pressable, ScrollView, Platform, Overlay, Button, Chip } = rn;
|
|
43
61
|
const FieldFrame = makeFieldFrame(rn);
|
|
44
62
|
|
|
45
63
|
// Keyboard focus is a web concern: a device moves its reader's focus into
|
|
@@ -48,11 +66,11 @@ export function makeSelect(rn) {
|
|
|
48
66
|
if (Platform.OS === "web" && node && typeof node.focus === "function") node.focus();
|
|
49
67
|
}
|
|
50
68
|
|
|
51
|
-
function OptionSheet(
|
|
69
|
+
function OptionSheet(props) {
|
|
70
|
+
const { t, options, isPicked, multiple, title, emptyText, listId, onPick, testID, footer } =
|
|
71
|
+
props;
|
|
52
72
|
const nodes = React.useRef([]);
|
|
53
|
-
const
|
|
54
|
-
const firstEnabled = options.findIndex((option) => !option.disabled);
|
|
55
|
-
const initial = chosen !== -1 && !options[chosen].disabled ? chosen : firstEnabled;
|
|
73
|
+
const initial = initialFocusIndex(options, isPicked);
|
|
56
74
|
// Focus lands on the current choice once, when the sheet mounts it; the
|
|
57
75
|
// browser scrolls a focused option into view in a long list.
|
|
58
76
|
const pendingFocus = React.useRef(true);
|
|
@@ -81,12 +99,13 @@ export function makeSelect(rn) {
|
|
|
81
99
|
nativeID: listId,
|
|
82
100
|
// Web only: native has no listbox, and ignores an unknown `role`.
|
|
83
101
|
role: "listbox",
|
|
102
|
+
...(multiple ? { "aria-multiselectable": true } : null),
|
|
84
103
|
accessibilityLabel: isText(title) ? String(title) : undefined,
|
|
85
104
|
keyboardShouldPersistTaps: "handled",
|
|
86
105
|
testID: testID ? `${testID}-options` : undefined,
|
|
87
106
|
},
|
|
88
107
|
...options.map((option, index) => {
|
|
89
|
-
const selected = option
|
|
108
|
+
const selected = isPicked(option);
|
|
90
109
|
// The web host still delivers keys to a disabled Pressable.
|
|
91
110
|
const pick = () => {
|
|
92
111
|
if (!option.disabled) onPick(option);
|
|
@@ -121,7 +140,7 @@ export function makeSelect(rn) {
|
|
|
121
140
|
{
|
|
122
141
|
flexDirection: "row",
|
|
123
142
|
alignItems: "center",
|
|
124
|
-
justifyContent: "space-between",
|
|
143
|
+
justifyContent: multiple ? "flex-start" : "space-between",
|
|
125
144
|
gap: t.rowGap,
|
|
126
145
|
minHeight: CONTROL_MIN_TARGET,
|
|
127
146
|
paddingHorizontal: t.paddingHorizontal,
|
|
@@ -132,15 +151,93 @@ export function makeSelect(rn) {
|
|
|
132
151
|
option.disabled ? { opacity: t.disabledOpacity } : null,
|
|
133
152
|
],
|
|
134
153
|
},
|
|
154
|
+
multiple ? checkboxBox(View, t, { checked: selected }) : null,
|
|
135
155
|
h(
|
|
136
156
|
Text,
|
|
137
157
|
{ style: [text, { flexShrink: 1 }, selected ? { fontWeight: "600" } : null] },
|
|
138
158
|
option.label,
|
|
139
159
|
),
|
|
140
|
-
selected ? h(Icon, { name: "check", size: 18, color: t.accent }) : null,
|
|
160
|
+
selected && !multiple ? h(Icon, { name: "check", size: 18, color: t.accent }) : null,
|
|
141
161
|
);
|
|
142
162
|
}),
|
|
143
163
|
),
|
|
164
|
+
footer || null,
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function DoneFooter({ doneText, onDone, testID }) {
|
|
169
|
+
return h(
|
|
170
|
+
View,
|
|
171
|
+
{ style: { flexDirection: "row", justifyContent: "flex-end" } },
|
|
172
|
+
h(Button, { title: doneText, onPress: onDone, testID: testID ? `${testID}-done` : undefined }),
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Chips when they fit the field's one line, else the count; measured on
|
|
177
|
+
// both hosts, so a narrow trigger never grows to hold them.
|
|
178
|
+
function MultiSummary({ t, picked, placeholder, selectedCountText, testID }) {
|
|
179
|
+
const [widths, setWidths] = React.useState(UNMEASURED);
|
|
180
|
+
const countText =
|
|
181
|
+
typeof selectedCountText === "function" ? selectedCountText : defaultSelectedCountText;
|
|
182
|
+
const measure = (key) => (event) => {
|
|
183
|
+
const width = event.nativeEvent.layout.width;
|
|
184
|
+
setWidths((own) => (own[key] === width ? own : { ...own, [key]: width }));
|
|
185
|
+
};
|
|
186
|
+
const mode = triggerSummary({ picked: picked.length, ...widths });
|
|
187
|
+
const text = { fontFamily: t.fontFamily, fontSize: t.fontSize };
|
|
188
|
+
const chips = () =>
|
|
189
|
+
picked.map((option) =>
|
|
190
|
+
h(Chip, {
|
|
191
|
+
key: `${typeof option.value}:${option.value}`,
|
|
192
|
+
label: option.label,
|
|
193
|
+
size: "sm",
|
|
194
|
+
style: TRIGGER_CHIP_STYLE,
|
|
195
|
+
}),
|
|
196
|
+
);
|
|
197
|
+
return h(
|
|
198
|
+
View,
|
|
199
|
+
{
|
|
200
|
+
onLayout: measure("available"),
|
|
201
|
+
style: { flexGrow: 1, flexShrink: 1, minWidth: 0, overflow: "hidden" },
|
|
202
|
+
testID: testID ? `${testID}-summary` : undefined,
|
|
203
|
+
},
|
|
204
|
+
mode === "chips"
|
|
205
|
+
? h(View, { style: { flexDirection: "row", gap: t.gap } }, ...chips())
|
|
206
|
+
: h(
|
|
207
|
+
Text,
|
|
208
|
+
{
|
|
209
|
+
numberOfLines: 1,
|
|
210
|
+
style: { ...text, color: mode === "count" ? t.textColor : t.placeholderColor },
|
|
211
|
+
},
|
|
212
|
+
mode === "count" ? countText(picked.length) : placeholder,
|
|
213
|
+
),
|
|
214
|
+
picked.length > 0
|
|
215
|
+
? h(
|
|
216
|
+
View,
|
|
217
|
+
{
|
|
218
|
+
"aria-hidden": true,
|
|
219
|
+
importantForAccessibility: "no-hide-descendants",
|
|
220
|
+
accessibilityElementsHidden: true,
|
|
221
|
+
style: {
|
|
222
|
+
position: "absolute",
|
|
223
|
+
top: 0,
|
|
224
|
+
left: 0,
|
|
225
|
+
width: MEASURE_SPAN,
|
|
226
|
+
opacity: 0,
|
|
227
|
+
pointerEvents: "none",
|
|
228
|
+
},
|
|
229
|
+
},
|
|
230
|
+
h(
|
|
231
|
+
View,
|
|
232
|
+
{
|
|
233
|
+
onLayout: measure("needed"),
|
|
234
|
+
style: { flexDirection: "row", alignSelf: "flex-start", gap: t.gap },
|
|
235
|
+
testID: testID ? `${testID}-measure` : undefined,
|
|
236
|
+
},
|
|
237
|
+
...chips(),
|
|
238
|
+
),
|
|
239
|
+
)
|
|
240
|
+
: null,
|
|
144
241
|
);
|
|
145
242
|
}
|
|
146
243
|
|
|
@@ -148,6 +245,11 @@ export function makeSelect(rn) {
|
|
|
148
245
|
const {
|
|
149
246
|
value,
|
|
150
247
|
onValueChange,
|
|
248
|
+
multiple = false,
|
|
249
|
+
values,
|
|
250
|
+
onValuesChange,
|
|
251
|
+
selectedCountText = defaultSelectedCountText,
|
|
252
|
+
doneText = "Done",
|
|
151
253
|
options,
|
|
152
254
|
placeholder = "Select",
|
|
153
255
|
title,
|
|
@@ -174,6 +276,8 @@ export function makeSelect(rn) {
|
|
|
174
276
|
}
|
|
175
277
|
const t = resolveFormControlTokens(theme, overrides);
|
|
176
278
|
const [open, setOpen] = React.useState(false);
|
|
279
|
+
// Null until the person ticks something: an untouched sheet follows `values`.
|
|
280
|
+
const [ownDraft, setDraft] = React.useState(null);
|
|
177
281
|
const [focused, setFocused] = React.useState(false);
|
|
178
282
|
const triggerRef = React.useRef(null);
|
|
179
283
|
const setRef = React.useMemo(() => shareRef(ref, triggerRef), [ref]);
|
|
@@ -181,14 +285,41 @@ export function makeSelect(rn) {
|
|
|
181
285
|
const noteId = React.useId();
|
|
182
286
|
const list = Array.isArray(options) ? options.filter(Boolean) : [];
|
|
183
287
|
const current = selectedOption(list, value);
|
|
288
|
+
const picked = multiple ? pickedOptions(list, values) : [];
|
|
289
|
+
const draft = ownDraft === null ? valueList(values) : ownDraft;
|
|
184
290
|
const invalid = isShown(error);
|
|
185
291
|
const sheetTitle = isShown(title) ? title : isText(label) ? label : undefined;
|
|
186
292
|
const name = spokenLabel(accessibilityLabel, label);
|
|
187
293
|
const shown = current ? current.label : placeholder;
|
|
294
|
+
const spokenChoice = multiple
|
|
295
|
+
? picked.length > 0
|
|
296
|
+
? picked.map((option) => option.label).filter(isText).join(", ")
|
|
297
|
+
: placeholder
|
|
298
|
+
: shown;
|
|
188
299
|
const show = () => {
|
|
189
|
-
if (
|
|
300
|
+
if (disabled) return;
|
|
301
|
+
if (multiple) setDraft(null);
|
|
302
|
+
setOpen(true);
|
|
190
303
|
};
|
|
304
|
+
// Closing any other way leaves the draft behind: only Done commits it.
|
|
191
305
|
const close = () => setOpen(false);
|
|
306
|
+
const done = () => {
|
|
307
|
+
const next = committedValues(list, draft);
|
|
308
|
+
close();
|
|
309
|
+
if (!sameValues(next, valueList(values)) && typeof onValuesChange === "function") {
|
|
310
|
+
onValuesChange(next, pickedOptions(list, next));
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
const pick = (option) => {
|
|
314
|
+
if (multiple) {
|
|
315
|
+
setDraft((own) => toggleValue(own === null ? valueList(values) : own, option.value));
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
close();
|
|
319
|
+
if (option.value !== value && typeof onValueChange === "function") {
|
|
320
|
+
onValueChange(option.value, option);
|
|
321
|
+
}
|
|
322
|
+
};
|
|
192
323
|
// The option that held focus is gone once the sheet closes. After the
|
|
193
324
|
// sheet unmounts, or its focus trap would pull focus straight back in.
|
|
194
325
|
const wasOpen = React.useRef(false);
|
|
@@ -239,7 +370,8 @@ export function makeSelect(rn) {
|
|
|
239
370
|
...(invalid ? { "aria-invalid": true } : null),
|
|
240
371
|
...(hasNote({ helper, error }) ? { "aria-describedby": noteId } : null),
|
|
241
372
|
// The choice is part of the name: a button's own label replaces its text.
|
|
242
|
-
accessibilityLabel:
|
|
373
|
+
accessibilityLabel:
|
|
374
|
+
[name, isText(spokenChoice) ? spokenChoice : null].filter(Boolean).join(", ") || undefined,
|
|
243
375
|
testID,
|
|
244
376
|
style: [
|
|
245
377
|
{
|
|
@@ -260,19 +392,21 @@ export function makeSelect(rn) {
|
|
|
260
392
|
style,
|
|
261
393
|
],
|
|
262
394
|
},
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
395
|
+
multiple
|
|
396
|
+
? h(MultiSummary, { t, picked, placeholder, selectedCountText, testID })
|
|
397
|
+
: h(
|
|
398
|
+
Text,
|
|
399
|
+
{
|
|
400
|
+
numberOfLines: 1,
|
|
401
|
+
style: {
|
|
402
|
+
flexShrink: 1,
|
|
403
|
+
color: current ? t.textColor : t.placeholderColor,
|
|
404
|
+
fontFamily: t.fontFamily,
|
|
405
|
+
fontSize: t.fontSize,
|
|
406
|
+
},
|
|
407
|
+
},
|
|
408
|
+
shown,
|
|
409
|
+
),
|
|
276
410
|
h(Icon, { name: "chevron-down", size: 18, color: t.placeholderColor }),
|
|
277
411
|
),
|
|
278
412
|
h(
|
|
@@ -293,17 +427,16 @@ export function makeSelect(rn) {
|
|
|
293
427
|
h(OptionSheet, {
|
|
294
428
|
t,
|
|
295
429
|
options: list,
|
|
296
|
-
|
|
430
|
+
multiple,
|
|
431
|
+
isPicked: multiple
|
|
432
|
+
? (option) => draft.includes(option.value)
|
|
433
|
+
: (option) => option.value === value,
|
|
297
434
|
title: sheetTitle,
|
|
298
435
|
emptyText,
|
|
299
436
|
listId,
|
|
300
437
|
testID,
|
|
301
|
-
onPick:
|
|
302
|
-
|
|
303
|
-
if (option.value !== value && typeof onValueChange === "function") {
|
|
304
|
-
onValueChange(option.value, option);
|
|
305
|
-
}
|
|
306
|
-
},
|
|
438
|
+
onPick: pick,
|
|
439
|
+
footer: multiple ? h(DoneFooter, { doneText, onDone: done, testID }) : null,
|
|
307
440
|
}),
|
|
308
441
|
),
|
|
309
442
|
);
|
package/dist/select.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
// `<Select>` (web). Binds ./select-view.js to react-native-web and the web
|
|
2
|
-
// `<Overlay>`; see ./primitives.js for why not the
|
|
2
|
+
// `<Overlay>`, `<Button>` and `<Chip>`; see ./primitives.js for why not the
|
|
3
|
+
// bare specifier.
|
|
3
4
|
|
|
4
5
|
import * as ReactNative from "react-native-web";
|
|
5
6
|
import { makeSelect } from "./select-view.js";
|
|
6
7
|
import { Overlay } from "./overlay.js";
|
|
8
|
+
import { Button } from "./button.js";
|
|
9
|
+
import { Chip } from "./chip.js";
|
|
7
10
|
|
|
8
11
|
export const Select = makeSelect({
|
|
9
12
|
View: ReactNative.View,
|
|
@@ -12,4 +15,6 @@ export const Select = makeSelect({
|
|
|
12
15
|
ScrollView: ReactNative.ScrollView,
|
|
13
16
|
Platform: ReactNative.Platform,
|
|
14
17
|
Overlay,
|
|
18
|
+
Button,
|
|
19
|
+
Chip,
|
|
15
20
|
});
|
package/dist/select.native.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
// `<Select>` (native). Binds ./select-view.js to React Native's own
|
|
2
|
-
// primitives and the native `<Overlay>`; only the
|
|
3
|
-
// ./select.js.
|
|
2
|
+
// primitives and the native `<Overlay>`, `<Button>` and `<Chip>`; only the
|
|
3
|
+
// imports differ from ./select.js.
|
|
4
4
|
|
|
5
5
|
import { View, Text, Pressable, ScrollView, Platform } from "react-native";
|
|
6
6
|
import { makeSelect } from "./select-view.js";
|
|
7
7
|
import { Overlay } from "./overlay.native.js";
|
|
8
|
+
import { Button } from "./button.native.js";
|
|
9
|
+
import { Chip } from "./chip.native.js";
|
|
8
10
|
|
|
9
|
-
export const Select = makeSelect({ View, Text, Pressable, ScrollView, Platform, Overlay });
|
|
11
|
+
export const Select = makeSelect({ View, Text, Pressable, ScrollView, Platform, Overlay, Button, Chip });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@colixsystems/widget-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.238.0",
|
|
4
4
|
"description": "Common widget interface for AppStudio. Implements WidgetManifest, WidgetContext, property schema, and helper hooks.",
|
|
5
5
|
"homepage": "https://github.com/Colix-AB/AppStudio",
|
|
6
6
|
"type": "module",
|