@octane-xplat/picker 0.13.0 → 0.15.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 +4 -4
- package/package.json +14 -13
- package/platforms/ios/src/XplatPickerProvider.swift +18 -17
- package/src/MaterialDropdown.android.tsrx +3 -1
- package/src/Select.web.tsrx +6 -4
- package/src/SwiftUIPicker.ios.tsrx +3 -1
- package/dist/native/MaterialDropdown.android.tsrx.js +0 -49
- package/dist/native/SwiftUIPicker.ios.tsrx.js +0 -49
- package/dist/native/android/index.js +0 -2
- package/dist/native/index.js +0 -0
- package/dist/native/ios/index.js +0 -2
- package/dist/native/octane-client-build.json +0 -8
- package/dist/web/Select.web.tsrx.js +0 -94
- package/dist/web/octane-client-build.json +0 -8
- package/dist/web/web/index.js +0 -2
package/README.md
CHANGED
|
@@ -12,11 +12,11 @@ There is no shared picker API at the package root. Each platform entry exports
|
|
|
12
12
|
its own component and types; import it from the platform subpath in a matching
|
|
13
13
|
platform-suffixed file:
|
|
14
14
|
|
|
15
|
-
| File suffix
|
|
16
|
-
|
|
|
17
|
-
| `*.ios.tsx`
|
|
15
|
+
| File suffix | Import | Component |
|
|
16
|
+
| --------------- | ------------------------------ | ------------------ |
|
|
17
|
+
| `*.ios.tsx` | `@octane-xplat/picker/ios` | `SwiftUIPicker` |
|
|
18
18
|
| `*.android.tsx` | `@octane-xplat/picker/android` | `MaterialDropdown` |
|
|
19
|
-
| `*.web.tsx`
|
|
19
|
+
| `*.web.tsx` | `@octane-xplat/picker/web` | `Select` |
|
|
20
20
|
|
|
21
21
|
```tsx
|
|
22
22
|
/** @jsxImportSource @nativescript-community/octane */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@octane-xplat/picker",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "Select control for Octane xplat — web select + SwiftUI picker (iOS) / Material dropdown (Android)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"android",
|
|
@@ -23,30 +23,31 @@
|
|
|
23
23
|
"directory": "packages/picker"
|
|
24
24
|
},
|
|
25
25
|
"files": [
|
|
26
|
-
"dist",
|
|
27
26
|
"types",
|
|
28
27
|
"src",
|
|
29
|
-
"platforms"
|
|
28
|
+
"platforms",
|
|
29
|
+
"!src/**/*.test.*",
|
|
30
|
+
"!src/**/*.spec.*"
|
|
30
31
|
],
|
|
31
32
|
"type": "module",
|
|
32
33
|
"exports": {
|
|
33
34
|
".": {
|
|
34
35
|
"types": "./types/index.d.ts",
|
|
35
|
-
"web": "./
|
|
36
|
-
"native": "./
|
|
37
|
-
"default": "./
|
|
36
|
+
"web": "./src/index.ts",
|
|
37
|
+
"native": "./src/index.ts",
|
|
38
|
+
"default": "./src/index.ts"
|
|
38
39
|
},
|
|
39
40
|
"./ios": {
|
|
40
41
|
"types": "./types/ios/index.d.ts",
|
|
41
|
-
"native": "./
|
|
42
|
+
"native": "./src/ios/index.ts"
|
|
42
43
|
},
|
|
43
44
|
"./android": {
|
|
44
45
|
"types": "./types/android/index.d.ts",
|
|
45
|
-
"native": "./
|
|
46
|
+
"native": "./src/android/index.ts"
|
|
46
47
|
},
|
|
47
48
|
"./web": {
|
|
48
49
|
"types": "./types/web/index.d.ts",
|
|
49
|
-
"web": "./
|
|
50
|
+
"web": "./src/web/index.ts"
|
|
50
51
|
}
|
|
51
52
|
},
|
|
52
53
|
"publishConfig": {
|
|
@@ -57,11 +58,11 @@
|
|
|
57
58
|
"@nativescript/swift-ui": "4.0.2"
|
|
58
59
|
},
|
|
59
60
|
"devDependencies": {
|
|
60
|
-
"@nativescript-community/octane": "0.2.
|
|
61
|
+
"@nativescript-community/octane": "0.2.5",
|
|
61
62
|
"@nativescript/core": "9.1.3",
|
|
62
63
|
"@octanejs/vite-plugin": "0.1.61",
|
|
63
64
|
"octane": "0.11.0",
|
|
64
|
-
"tsrx-typegen": "0.
|
|
65
|
+
"tsrx-typegen": "0.3.0",
|
|
65
66
|
"typescript": "5.9.3",
|
|
66
67
|
"vite": "8.3.0"
|
|
67
68
|
},
|
|
@@ -88,8 +89,8 @@
|
|
|
88
89
|
}
|
|
89
90
|
},
|
|
90
91
|
"scripts": {
|
|
91
|
-
"build": "vite build && vite build --mode native && tsc -p tsconfig.types.json && node ../../scripts/check-native-dist.mjs",
|
|
92
92
|
"test:packed": "node tests/packed-consumer.mjs",
|
|
93
|
-
"pack:check": "tsrx-typegen --pack-check"
|
|
93
|
+
"pack:check": "tsrx-typegen --pack-check",
|
|
94
|
+
"typegen": "tsc -p tsconfig.types.json"
|
|
94
95
|
}
|
|
95
96
|
}
|
|
@@ -65,25 +65,26 @@ public final class XplatPickerProvider: UIViewController, SwiftUIProvider {
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
public func updateData(data: NSDictionary) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
if let value = data["value"] as? String { model.value = value }
|
|
73
|
-
if let disabled = data["disabled"] as? NSNumber { model.disabled = disabled.boolValue }
|
|
74
|
-
if let options = data["options"] as? [[String: Any]] {
|
|
75
|
-
model.options = options.compactMap { option in
|
|
76
|
-
guard let value = option["value"] as? String,
|
|
77
|
-
let label = option["label"] as? String
|
|
78
|
-
else { return nil }
|
|
68
|
+
let options = ((data["options"] as? [[String: Any]]) ?? []).compactMap { option -> PickerOption? in
|
|
69
|
+
guard let value = option["value"] as? String,
|
|
70
|
+
let label = option["label"] as? String
|
|
71
|
+
else { return nil }
|
|
79
72
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
73
|
+
return PickerOption(
|
|
74
|
+
value: value,
|
|
75
|
+
label: label,
|
|
76
|
+
disabled: (option["disabled"] as? NSNumber)?.boolValue ?? false,
|
|
77
|
+
)
|
|
86
78
|
}
|
|
79
|
+
|
|
80
|
+
// Full replace — matching the Kotlin provider: absent keys reset to
|
|
81
|
+
// defaults and a missing value falls back to the first option, so a
|
|
82
|
+
// partial payload cannot leave divergent state across platforms.
|
|
83
|
+
model.label = data["label"] as? String ?? ""
|
|
84
|
+
model.accessibilityLabel = data["accessibilityLabel"] as? String ?? ""
|
|
85
|
+
model.value = data["value"] as? String ?? options.first?.value ?? ""
|
|
86
|
+
model.disabled = (data["disabled"] as? NSNumber)?.boolValue ?? false
|
|
87
|
+
model.options = options
|
|
87
88
|
}
|
|
88
89
|
|
|
89
90
|
public var onEvent: ((NSDictionary) -> Void)?
|
|
@@ -22,7 +22,9 @@ registerJetpackCompose('xplat-material-dropdown', (owner: any) =>
|
|
|
22
22
|
export function MaterialDropdown(props: MaterialDropdownProps) @{
|
|
23
23
|
const controlled = props.selectedKey !== undefined
|
|
24
24
|
const [internalKey, setInternalKey] = useState(props.defaultSelectedKey ?? props.items[0]?.key ?? '')
|
|
25
|
-
|
|
25
|
+
// Uncontrolled with a blank internal selection displays the first item
|
|
26
|
+
// once items arrive — matching the other leaves' auto-select-first.
|
|
27
|
+
const selectedKey = controlled ? props.selectedKey! : internalKey || (props.items[0]?.key ?? '')
|
|
26
28
|
const data = {
|
|
27
29
|
label: props.label,
|
|
28
30
|
accessibilityLabel: props.accessibilityLabel ?? props.label,
|
package/src/Select.web.tsrx
CHANGED
|
@@ -6,15 +6,17 @@ import type { SelectProps } from './web/types'
|
|
|
6
6
|
export function Select(props: SelectProps) @{
|
|
7
7
|
const controlled = props.value !== undefined
|
|
8
8
|
const [internalValue, setInternalValue] = useState(props.defaultValue ?? props.options[0]?.value ?? '')
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
// Uncontrolled with a blank internal selection displays the first option
|
|
10
|
+
// once options exist — the default is auto-select-first.
|
|
11
|
+
const value = controlled ? props.value! : internalValue || (props.options[0]?.value ?? '')
|
|
11
12
|
|
|
12
13
|
<label className={props.className} style={props.style}>
|
|
13
|
-
<
|
|
14
|
+
{/* The wrapping <label> supplies the implicit accessible name;
|
|
15
|
+
aria-label overrides it with accessibilityLabel when given. */}
|
|
16
|
+
<span>{props.label}</span>
|
|
14
17
|
<select
|
|
15
18
|
id={props.id}
|
|
16
19
|
aria-label={props.accessibilityLabel ?? props.label}
|
|
17
|
-
aria-labelledby={labelId}
|
|
18
20
|
value={value}
|
|
19
21
|
disabled={props.disabled}
|
|
20
22
|
onChange={(event: any) => {
|
|
@@ -22,7 +22,9 @@ registerSwiftUI('xplat-swiftui-picker', (owner: any) =>
|
|
|
22
22
|
export function SwiftUIPicker(props: SwiftUIPickerProps) @{
|
|
23
23
|
const controlled = props.selection !== undefined
|
|
24
24
|
const [internalSelection, setInternalSelection] = useState(props.defaultSelection ?? props.options[0]?.id ?? '')
|
|
25
|
-
|
|
25
|
+
// Uncontrolled with a blank internal selection displays the first option
|
|
26
|
+
// once options arrive — matching the other leaves' auto-select-first.
|
|
27
|
+
const selection = controlled ? props.selection! : internalSelection || (props.options[0]?.id ?? '')
|
|
26
28
|
const update = (nextSelection: string) => {
|
|
27
29
|
if (!controlled) setInternalSelection(nextSelection)
|
|
28
30
|
props.onSelectionChange?.(nextSelection)
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { defineUniversalComponent, hookSlots, registerElement, universalPlan, universalValue, useState } from "@nativescript-community/octane";
|
|
2
|
-
import { ComposeDataDriver, JetpackCompose, registerJetpackCompose } from "@nativescript/jetpack-compose";
|
|
3
|
-
//#region src/MaterialDropdown.android.tsrx
|
|
4
|
-
var _h$0 = /* @__PURE__ */ Symbol(/* @__PURE__ */ hookSlots(1));
|
|
5
|
-
var __octaneUniversalPlan0 = universalPlan("nativescript", {
|
|
6
|
-
"kind": "host",
|
|
7
|
-
"type": "xplatandroidpicker",
|
|
8
|
-
"props": { "composeId": "xplat-material-dropdown" },
|
|
9
|
-
"bindings": [
|
|
10
|
-
["id", 0],
|
|
11
|
-
["className", 1],
|
|
12
|
-
["style", 2],
|
|
13
|
-
["data", 3],
|
|
14
|
-
["onComposeEvent", 4]
|
|
15
|
-
]
|
|
16
|
-
});
|
|
17
|
-
registerElement("xplatandroidpicker", JetpackCompose);
|
|
18
|
-
registerJetpackCompose("xplat-material-dropdown", (owner) => new ComposeDataDriver(new com.octanexplat.nativepicker.XplatPickerProvider(), owner));
|
|
19
|
-
var MaterialDropdown = defineUniversalComponent("nativescript", function MaterialDropdown(props) {
|
|
20
|
-
const controlled = props.selectedKey !== void 0;
|
|
21
|
-
const [internalKey, setInternalKey] = useState(props.defaultSelectedKey ?? props.items[0]?.key ?? "", _h$0);
|
|
22
|
-
const selectedKey = controlled ? props.selectedKey : internalKey;
|
|
23
|
-
const data = {
|
|
24
|
-
label: props.label,
|
|
25
|
-
accessibilityLabel: props.accessibilityLabel ?? props.label,
|
|
26
|
-
options: props.items.map((item) => ({
|
|
27
|
-
value: item.key,
|
|
28
|
-
label: item.text,
|
|
29
|
-
disabled: item.enabled === false ? 1 : 0
|
|
30
|
-
})),
|
|
31
|
-
value: selectedKey,
|
|
32
|
-
disabled: props.enabled === false ? 1 : 0
|
|
33
|
-
};
|
|
34
|
-
const update = (nextKey) => {
|
|
35
|
-
if (!controlled) setInternalKey(nextKey);
|
|
36
|
-
props.onSelectedKeyChange?.(nextKey);
|
|
37
|
-
};
|
|
38
|
-
return universalValue(__octaneUniversalPlan0, [
|
|
39
|
-
props.id,
|
|
40
|
-
props.className,
|
|
41
|
-
props.style,
|
|
42
|
-
data,
|
|
43
|
-
(event) => {
|
|
44
|
-
if (typeof event.data === "string") update(event.data);
|
|
45
|
-
}
|
|
46
|
-
]);
|
|
47
|
-
}, { "module": "@nativescript-community/octane" });
|
|
48
|
-
//#endregion
|
|
49
|
-
export { MaterialDropdown };
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { defineUniversalComponent, hookSlots, registerElement, universalPlan, universalValue, useState } from "@nativescript-community/octane";
|
|
2
|
-
import { SwiftUI, UIDataDriver, registerSwiftUI } from "@nativescript/swift-ui";
|
|
3
|
-
//#region src/SwiftUIPicker.ios.tsrx
|
|
4
|
-
var _h$0 = /* @__PURE__ */ Symbol(/* @__PURE__ */ hookSlots(1));
|
|
5
|
-
var __octaneUniversalPlan0 = universalPlan("nativescript", {
|
|
6
|
-
"kind": "host",
|
|
7
|
-
"type": "xplatiospicker",
|
|
8
|
-
"props": { "swiftId": "xplat-swiftui-picker" },
|
|
9
|
-
"bindings": [
|
|
10
|
-
["id", 0],
|
|
11
|
-
["className", 1],
|
|
12
|
-
["style", 2],
|
|
13
|
-
["data", 3],
|
|
14
|
-
["onSwiftUIEvent", 4]
|
|
15
|
-
]
|
|
16
|
-
});
|
|
17
|
-
registerElement("xplatiospicker", SwiftUI);
|
|
18
|
-
registerSwiftUI("xplat-swiftui-picker", (owner) => new UIDataDriver(new XplatPickerProvider(), owner));
|
|
19
|
-
var SwiftUIPicker = defineUniversalComponent("nativescript", function SwiftUIPicker(props) {
|
|
20
|
-
const controlled = props.selection !== void 0;
|
|
21
|
-
const [internalSelection, setInternalSelection] = useState(props.defaultSelection ?? props.options[0]?.id ?? "", _h$0);
|
|
22
|
-
const selection = controlled ? props.selection : internalSelection;
|
|
23
|
-
const update = (nextSelection) => {
|
|
24
|
-
if (!controlled) setInternalSelection(nextSelection);
|
|
25
|
-
props.onSelectionChange?.(nextSelection);
|
|
26
|
-
};
|
|
27
|
-
return universalValue(__octaneUniversalPlan0, [
|
|
28
|
-
props.id,
|
|
29
|
-
props.className,
|
|
30
|
-
props.style,
|
|
31
|
-
{
|
|
32
|
-
label: props.label,
|
|
33
|
-
accessibilityLabel: props.accessibilityLabel ?? props.label,
|
|
34
|
-
options: props.options.map((option) => ({
|
|
35
|
-
value: option.id,
|
|
36
|
-
label: option.title,
|
|
37
|
-
disabled: option.disabled ?? false
|
|
38
|
-
})),
|
|
39
|
-
value: selection,
|
|
40
|
-
disabled: props.disabled ?? false
|
|
41
|
-
},
|
|
42
|
-
(event) => {
|
|
43
|
-
const nextSelection = event.data?.value;
|
|
44
|
-
if (typeof nextSelection === "string") update(nextSelection);
|
|
45
|
-
}
|
|
46
|
-
]);
|
|
47
|
-
}, { "module": "@nativescript-community/octane" });
|
|
48
|
-
//#endregion
|
|
49
|
-
export { SwiftUIPicker };
|
package/dist/native/index.js
DELETED
|
File without changes
|
package/dist/native/ios/index.js
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import { __s, bag13, bag5, child, clone, createScopedElement, delegateEvents, hookSlots, mapSlot, setEventHandler, setSelectValue, setStyle, sibling, template, useState } from "octane";
|
|
2
|
-
import { childTextHoleUpdate, compilerMemoRegion, hookMemoEqual, setAriaAttributeIfChanged, setAttributeIfChanged, setBooleanAttributeIfChanged, setClassNameIfChanged, setPlainAttributeIfChanged } from "octane/internal/client";
|
|
3
|
-
//#region src/Select.web.tsrx
|
|
4
|
-
delegateEvents(["change"]);
|
|
5
|
-
var _t$0 = /* @__PURE__ */ template("<option></option>");
|
|
6
|
-
var _t$1 = /* @__PURE__ */ template("<label><span></span><select><!></select></label>");
|
|
7
|
-
var _hs$ = /* @__PURE__ */ hookSlots(2);
|
|
8
|
-
var _key$1 = (option) => option.value;
|
|
9
|
-
function __item$2(option, __s, __extra) {
|
|
10
|
-
let _b = __s.slots[0];
|
|
11
|
-
if (_b === void 0) {
|
|
12
|
-
const _root = clone(_t$0);
|
|
13
|
-
_b = bag5(__s, _root, void 0, _root, void 0, null, __s);
|
|
14
|
-
}
|
|
15
|
-
_b.a = setAttributeIfChanged(option.value, _b.a, _b.b, "value");
|
|
16
|
-
_b.c = setBooleanAttributeIfChanged(option.disabled, _b.c, _b.b, "disabled");
|
|
17
|
-
{
|
|
18
|
-
const _v = option.label;
|
|
19
|
-
_b.d = childTextHoleUpdate(__s, 1, _b.b, _v, _b.d, _b.e);
|
|
20
|
-
_b.e = _v;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
var Select = /* @__PURE__ */ __s(function Select(props, __s, __extra) {
|
|
24
|
-
const __memoRegion = compilerMemoRegion(__s, _hs$ + 0);
|
|
25
|
-
const __memoCommitted = __memoRegion.auto;
|
|
26
|
-
let __memoCache = __memoCommitted === void 0 ? [] : __memoCommitted;
|
|
27
|
-
let __mapItems;
|
|
28
|
-
let __mapMethod;
|
|
29
|
-
const controlled = props.value !== void 0;
|
|
30
|
-
const [internalValue, setInternalValue] = useState(props.defaultValue ?? props.options[0]?.value ?? "", _hs$ + 0);
|
|
31
|
-
const value = controlled ? props.value : internalValue;
|
|
32
|
-
const labelId = props.id ? `${props.id}-label` : void 0;
|
|
33
|
-
if (__s.block.pending && !__s.block.crossRenderUpdate) return;
|
|
34
|
-
let _b = __s.slots[0];
|
|
35
|
-
if (_b === void 0) {
|
|
36
|
-
let _m10;
|
|
37
|
-
const _root = clone(_t$1);
|
|
38
|
-
const _el0 = child(_root);
|
|
39
|
-
const _el1 = sibling(_el0, 1);
|
|
40
|
-
setSelectValue(_el1, value);
|
|
41
|
-
setEventHandler(_el1, "$ochange", (event) => {
|
|
42
|
-
const nextValue = event.target.value;
|
|
43
|
-
if (!controlled) setInternalValue(nextValue);
|
|
44
|
-
props.onChange?.(nextValue);
|
|
45
|
-
});
|
|
46
|
-
_m10 = child(_el1);
|
|
47
|
-
_b = bag13(__s, _root, void 0, _root, void 0, void 0, _el0, void 0, _el1, void 0, void 0, void 0, _m10, null, __s);
|
|
48
|
-
} else {
|
|
49
|
-
setSelectValue(_b.g, value);
|
|
50
|
-
setEventHandler(_b.g, "$ochange", (event) => {
|
|
51
|
-
const nextValue = event.target.value;
|
|
52
|
-
if (!controlled) setInternalValue(nextValue);
|
|
53
|
-
props.onChange?.(nextValue);
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
_b.a = setClassNameIfChanged(props.className, _b.a, _b.b);
|
|
57
|
-
{
|
|
58
|
-
const _v = props.style;
|
|
59
|
-
if (_b.c !== _v) {
|
|
60
|
-
setStyle(_b.b, _v, _b.c);
|
|
61
|
-
_b.c = _v;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
_b.d = setPlainAttributeIfChanged(labelId, _b.d, _b.e, "id");
|
|
65
|
-
_b.f = setPlainAttributeIfChanged(props.id, _b.f, _b.g, "id");
|
|
66
|
-
_b.h = setAriaAttributeIfChanged(props.accessibilityLabel ?? props.label, _b.h, _b.g, "aria-label");
|
|
67
|
-
_b.i = setAriaAttributeIfChanged(labelId, _b.i, _b.g, "aria-labelledby");
|
|
68
|
-
_b.j = setBooleanAttributeIfChanged(props.disabled, _b.j, _b.g, "disabled");
|
|
69
|
-
{
|
|
70
|
-
const _v = props.label;
|
|
71
|
-
_b.l = childTextHoleUpdate(__s, 1, _b.e, _v, _b.l, _b.m);
|
|
72
|
-
_b.m = _v;
|
|
73
|
-
}
|
|
74
|
-
{
|
|
75
|
-
const _v = (__mapItems = props.options, __mapMethod = __mapItems.map, __mapItems);
|
|
76
|
-
const __mapNative = mapSlot(_v, __mapMethod);
|
|
77
|
-
{
|
|
78
|
-
const __memoDep = _v;
|
|
79
|
-
if (__s.slots[2] === void 0 || !__mapNative || __memoCache[1] !== true || !hookMemoEqual(__memoCache[0], __memoDep)) {
|
|
80
|
-
mapSlot(__s, 2, _b.g, _v, __mapMethod, __mapNative, (option) => createScopedElement("option", {
|
|
81
|
-
key: option.value,
|
|
82
|
-
value: option.value,
|
|
83
|
-
disabled: option.disabled
|
|
84
|
-
}, () => option.label), _key$1, __item$2, 27, void 0, _b.k, 1);
|
|
85
|
-
if (__memoCache === __memoCommitted) __memoCache = __memoCache.slice();
|
|
86
|
-
__memoCache[0] = __memoDep;
|
|
87
|
-
__memoCache[1] = __mapNative;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
if (__memoCache !== __memoCommitted) __memoRegion.auto = __memoCache;
|
|
92
|
-
});
|
|
93
|
-
//#endregion
|
|
94
|
-
export { Select };
|
package/dist/web/web/index.js
DELETED