@tamagui/focusable 1.0.1-beta.103
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/dist/cjs/focusable.js +16 -0
- package/dist/cjs/focusable.js.map +7 -0
- package/dist/cjs/focusableInputHOC.js +92 -0
- package/dist/cjs/focusableInputHOC.js.map +7 -0
- package/dist/cjs/index.js +20 -0
- package/dist/cjs/index.js.map +7 -0
- package/dist/cjs/registerFocusable.js +37 -0
- package/dist/cjs/registerFocusable.js.map +7 -0
- package/dist/cjs/registerFocusable.native.js +60 -0
- package/dist/cjs/registerFocusable.native.js.map +7 -0
- package/dist/cjs/useControllableState.js +67 -0
- package/dist/cjs/useControllableState.js.map +7 -0
- package/dist/esm/focusable.js +1 -0
- package/dist/esm/focusable.js.map +7 -0
- package/dist/esm/focusableInputHOC.js +68 -0
- package/dist/esm/focusableInputHOC.js.map +7 -0
- package/dist/esm/index.js +4 -0
- package/dist/esm/index.js.map +7 -0
- package/dist/esm/registerFocusable.js +12 -0
- package/dist/esm/registerFocusable.js.map +7 -0
- package/dist/esm/registerFocusable.native.js +35 -0
- package/dist/esm/registerFocusable.native.js.map +7 -0
- package/dist/esm/useControllableState.js +44 -0
- package/dist/esm/useControllableState.js.map +7 -0
- package/dist/jsx/focusable.js +1 -0
- package/dist/jsx/focusable.js.map +7 -0
- package/dist/jsx/focusableInputHOC.js +49 -0
- package/dist/jsx/focusableInputHOC.js.map +7 -0
- package/dist/jsx/index.js +4 -0
- package/dist/jsx/index.js.map +7 -0
- package/dist/jsx/registerFocusable.js +12 -0
- package/dist/jsx/registerFocusable.js.map +7 -0
- package/dist/jsx/registerFocusable.native.js +35 -0
- package/dist/jsx/registerFocusable.native.js.map +7 -0
- package/dist/jsx/useControllableState.js +44 -0
- package/dist/jsx/useControllableState.js.map +7 -0
- package/package.json +38 -0
- package/src/focusable.ts +1 -0
- package/src/focusableInputHOC.tsx +65 -0
- package/src/index.ts +3 -0
- package/src/registerFocusable.native.ts +36 -0
- package/src/registerFocusable.ts +13 -0
- package/types/focusable.d.ts +5 -0
- package/types/focusable.d.ts.map +1 -0
- package/types/focusableInputHOC.d.ts +2 -0
- package/types/focusableInputHOC.d.ts.map +1 -0
- package/types/index.d.ts +4 -0
- package/types/index.d.ts.map +1 -0
- package/types/registerFocusable.d.ts +5 -0
- package/types/registerFocusable.d.ts.map +1 -0
- package/types/registerFocusable.native.d.ts +5 -0
- package/types/registerFocusable.native.d.ts.map +1 -0
- package/types/useControllableState.d.ts +11 -0
- package/types/useControllableState.d.ts.map +1 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __copyProps = (to, from, except, desc) => {
|
|
6
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
7
|
+
for (let key of __getOwnPropNames(from))
|
|
8
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
9
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
10
|
+
}
|
|
11
|
+
return to;
|
|
12
|
+
};
|
|
13
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
14
|
+
var focusable_exports = {};
|
|
15
|
+
module.exports = __toCommonJS(focusable_exports);
|
|
16
|
+
//# sourceMappingURL=focusable.js.map
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __defProps = Object.defineProperties;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
8
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
9
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
10
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
11
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
12
|
+
var __spreadValues = (a, b) => {
|
|
13
|
+
for (var prop in b || (b = {}))
|
|
14
|
+
if (__hasOwnProp.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
if (__getOwnPropSymbols)
|
|
17
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
18
|
+
if (__propIsEnum.call(b, prop))
|
|
19
|
+
__defNormalProp(a, prop, b[prop]);
|
|
20
|
+
}
|
|
21
|
+
return a;
|
|
22
|
+
};
|
|
23
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
24
|
+
var __export = (target, all) => {
|
|
25
|
+
for (var name in all)
|
|
26
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
27
|
+
};
|
|
28
|
+
var __copyProps = (to, from, except, desc) => {
|
|
29
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
30
|
+
for (let key of __getOwnPropNames(from))
|
|
31
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
32
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
33
|
+
}
|
|
34
|
+
return to;
|
|
35
|
+
};
|
|
36
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod));
|
|
37
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
38
|
+
var focusableInputHOC_exports = {};
|
|
39
|
+
__export(focusableInputHOC_exports, {
|
|
40
|
+
focusableInputHOC: () => focusableInputHOC
|
|
41
|
+
});
|
|
42
|
+
module.exports = __toCommonJS(focusableInputHOC_exports);
|
|
43
|
+
var import_compose_refs = require("@tamagui/compose-refs");
|
|
44
|
+
var import_core = require("@tamagui/core");
|
|
45
|
+
var import_react = __toESM(require("react"));
|
|
46
|
+
var import_react2 = require("react");
|
|
47
|
+
var import_registerFocusable = require("./registerFocusable");
|
|
48
|
+
function focusableInputHOC(Component) {
|
|
49
|
+
return (0, import_react2.forwardRef)((props, ref) => {
|
|
50
|
+
const isInput = (0, import_core.isTamaguiComponent)(Component) && Component.staticConfig.isInput;
|
|
51
|
+
const inputValue = (0, import_react.useRef)(props.value || props.defaultValue || "");
|
|
52
|
+
const inputRef = (0, import_react2.useCallback)((input) => {
|
|
53
|
+
if (!props.id)
|
|
54
|
+
return;
|
|
55
|
+
if (!input)
|
|
56
|
+
return;
|
|
57
|
+
(0, import_registerFocusable.registerFocusable)(props.id, __spreadValues({
|
|
58
|
+
focus: input.focus
|
|
59
|
+
}, isInput && {
|
|
60
|
+
focusAndSelect() {
|
|
61
|
+
input.focus();
|
|
62
|
+
if (input.setSelection && typeof inputValue.current === "string") {
|
|
63
|
+
input.setSelection(0, inputValue.current.length);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}));
|
|
67
|
+
}, [props.id]);
|
|
68
|
+
const combinedRefs = (0, import_compose_refs.composeRefs)(ref, inputRef);
|
|
69
|
+
(0, import_react2.useEffect)(() => {
|
|
70
|
+
if (!props.id)
|
|
71
|
+
return;
|
|
72
|
+
return () => {
|
|
73
|
+
(0, import_registerFocusable.unregisterFocusable)(props.id);
|
|
74
|
+
};
|
|
75
|
+
}, [props.id]);
|
|
76
|
+
const finalProps = isInput ? __spreadProps(__spreadValues({}, props), {
|
|
77
|
+
onChangeText(value) {
|
|
78
|
+
var _a;
|
|
79
|
+
inputValue.current = value;
|
|
80
|
+
(_a = props.onChangeText) == null ? void 0 : _a.call(props, value);
|
|
81
|
+
}
|
|
82
|
+
}) : props;
|
|
83
|
+
return /* @__PURE__ */ import_react.default.createElement(Component, __spreadValues({
|
|
84
|
+
ref: combinedRefs
|
|
85
|
+
}, finalProps));
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
89
|
+
0 && (module.exports = {
|
|
90
|
+
focusableInputHOC
|
|
91
|
+
});
|
|
92
|
+
//# sourceMappingURL=focusableInputHOC.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/focusableInputHOC.tsx"],
|
|
4
|
+
"sourcesContent": ["import { composeRefs } from '@tamagui/compose-refs'\nimport { isTamaguiComponent } from '@tamagui/core'\nimport React, { useRef } from 'react'\nimport { forwardRef, useCallback, useEffect } from 'react'\n\nimport { registerFocusable, unregisterFocusable } from './registerFocusable'\n\nexport function focusableInputHOC<A extends Function>(Component: A): A {\n return forwardRef(\n (\n props: {\n id?: string\n onChangeText?: (val: string) => void\n value?: string\n defaultValue?: string\n },\n ref\n ) => {\n const isInput = isTamaguiComponent(Component) && Component.staticConfig.isInput\n const inputValue = useRef(props.value || props.defaultValue || '')\n\n const inputRef = useCallback(\n (input) => {\n if (!props.id) return\n if (!input) return\n registerFocusable(props.id, {\n focus: input.focus,\n\n ...(isInput && {\n // react-native doesn't support programmatic .select()\n focusAndSelect() {\n input.focus()\n if (input.setSelection && typeof inputValue.current === 'string') {\n input.setSelection(0, inputValue.current.length)\n }\n },\n }),\n })\n },\n [props.id]\n )\n\n const combinedRefs = composeRefs(ref, inputRef)\n\n useEffect(() => {\n if (!props.id) return\n return () => {\n unregisterFocusable(props.id!)\n }\n }, [props.id])\n\n const finalProps = isInput\n ? {\n ...props,\n onChangeText(value) {\n inputValue.current = value\n props.onChangeText?.(value)\n },\n }\n : props\n\n return <Component ref={combinedRefs} {...finalProps} />\n }\n ) as any\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAA4B;AAC5B,kBAAmC;AACnC,mBAA8B;AAC9B,oBAAmD;AAEnD,+BAAuD;AAEhD,2BAA+C,WAAiB;AACrE,SAAO,8BACL,CACE,OAMA,QACG;AACH,UAAM,UAAU,oCAAmB,SAAS,KAAK,UAAU,aAAa;AACxE,UAAM,aAAa,yBAAO,MAAM,SAAS,MAAM,gBAAgB,EAAE;AAEjE,UAAM,WAAW,+BACf,CAAC,UAAU;AACT,UAAI,CAAC,MAAM;AAAI;AACf,UAAI,CAAC;AAAO;AACZ,sDAAkB,MAAM,IAAI;AAAA,QAC1B,OAAO,MAAM;AAAA,SAET,WAAW;AAAA,QAEb,iBAAiB;AACf,gBAAM,MAAM;AACZ,cAAI,MAAM,gBAAgB,OAAO,WAAW,YAAY,UAAU;AAChE,kBAAM,aAAa,GAAG,WAAW,QAAQ,MAAM;AAAA,UACjD;AAAA,QACF;AAAA,MACF,EACD;AAAA,IACH,GACA,CAAC,MAAM,EAAE,CACX;AAEA,UAAM,eAAe,qCAAY,KAAK,QAAQ;AAE9C,iCAAU,MAAM;AACd,UAAI,CAAC,MAAM;AAAI;AACf,aAAO,MAAM;AACX,0DAAoB,MAAM,EAAG;AAAA,MAC/B;AAAA,IACF,GAAG,CAAC,MAAM,EAAE,CAAC;AAEb,UAAM,aAAa,UACf,iCACK,QADL;AAAA,MAEE,aAAa,OAAO;AAtDhC;AAuDc,mBAAW,UAAU;AACrB,oBAAM,iBAAN,+BAAqB;AAAA,MACvB;AAAA,IACF,KACA;AAEJ,WAAO,mDAAC;AAAA,MAAU,KAAK;AAAA,OAAkB,WAAY;AAAA,EACvD,CACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __copyProps = (to, from, except, desc) => {
|
|
6
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
7
|
+
for (let key of __getOwnPropNames(from))
|
|
8
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
9
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
10
|
+
}
|
|
11
|
+
return to;
|
|
12
|
+
};
|
|
13
|
+
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
14
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
15
|
+
var src_exports = {};
|
|
16
|
+
module.exports = __toCommonJS(src_exports);
|
|
17
|
+
__reExport(src_exports, require("./registerFocusable"), module.exports);
|
|
18
|
+
__reExport(src_exports, require("./focusableInputHOC"), module.exports);
|
|
19
|
+
__reExport(src_exports, require("./focusable"), module.exports);
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/index.ts"],
|
|
4
|
+
"sourcesContent": ["export * from './registerFocusable'\nexport * from './focusableInputHOC'\nexport * from './focusable'\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;AAAA;AAAA;AAAA,wBAAc,gCAAd;AACA,wBAAc,gCADd;AAEA,wBAAc,wBAFd;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
var registerFocusable_exports = {};
|
|
19
|
+
__export(registerFocusable_exports, {
|
|
20
|
+
focusFocusable: () => focusFocusable,
|
|
21
|
+
registerFocusable: () => registerFocusable,
|
|
22
|
+
unregisterFocusable: () => unregisterFocusable
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(registerFocusable_exports);
|
|
25
|
+
const registerFocusable = (id, input) => {
|
|
26
|
+
};
|
|
27
|
+
const unregisterFocusable = (id) => {
|
|
28
|
+
};
|
|
29
|
+
const focusFocusable = (id) => {
|
|
30
|
+
};
|
|
31
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
32
|
+
0 && (module.exports = {
|
|
33
|
+
focusFocusable,
|
|
34
|
+
registerFocusable,
|
|
35
|
+
unregisterFocusable
|
|
36
|
+
});
|
|
37
|
+
//# sourceMappingURL=registerFocusable.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/registerFocusable.ts"],
|
|
4
|
+
"sourcesContent": ["import { Focusable } from './focusable'\n\nexport const registerFocusable = (id: string, input: Focusable) => {\n // noop focus is handed natively\n}\n\nexport const unregisterFocusable = (id: string) => {\n // noop focus is handed natively\n}\n\nexport const focusFocusable = (id: string) => {\n // noop focus is handed natively\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEO,MAAM,oBAAoB,CAAC,IAAY,UAAqB;AAEnE;AAEO,MAAM,sBAAsB,CAAC,OAAe;AAEnD;AAEO,MAAM,iBAAiB,CAAC,OAAe;AAE9C;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
var registerFocusable_native_exports = {};
|
|
19
|
+
__export(registerFocusable_native_exports, {
|
|
20
|
+
focusFocusable: () => focusFocusable,
|
|
21
|
+
registerFocusable: () => registerFocusable,
|
|
22
|
+
unregisterFocusable: () => unregisterFocusable
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(registerFocusable_native_exports);
|
|
25
|
+
const InputsMap = /* @__PURE__ */ new Map();
|
|
26
|
+
const registerFocusable = (id, input) => {
|
|
27
|
+
if (process.env.NODE_ENV !== "production") {
|
|
28
|
+
if (InputsMap.has(id)) {
|
|
29
|
+
console.warn(`Warning, duplicate ID for input: ${id}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
InputsMap.set(id, input);
|
|
33
|
+
return () => {
|
|
34
|
+
InputsMap.delete(id);
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
const unregisterFocusable = (id) => {
|
|
38
|
+
InputsMap.delete(id);
|
|
39
|
+
};
|
|
40
|
+
const focusFocusable = (id, select = false) => {
|
|
41
|
+
const input = InputsMap.get(id);
|
|
42
|
+
if (!input) {
|
|
43
|
+
if (process.env.NODE_ENV !== "production") {
|
|
44
|
+
console.warn("No input found for id", id);
|
|
45
|
+
}
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (select || !input.focusAndSelect) {
|
|
49
|
+
input.focus();
|
|
50
|
+
} else {
|
|
51
|
+
input.focusAndSelect();
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
55
|
+
0 && (module.exports = {
|
|
56
|
+
focusFocusable,
|
|
57
|
+
registerFocusable,
|
|
58
|
+
unregisterFocusable
|
|
59
|
+
});
|
|
60
|
+
//# sourceMappingURL=registerFocusable.native.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/registerFocusable.native.ts"],
|
|
4
|
+
"sourcesContent": ["// used for focusing on native\n\nimport { Focusable } from './focusable'\n\nconst InputsMap = new Map<string, Focusable>()\n\nexport const registerFocusable = (id: string, input: Focusable) => {\n if (process.env.NODE_ENV !== 'production') {\n if (InputsMap.has(id)) {\n console.warn(`Warning, duplicate ID for input: ${id}`)\n }\n }\n InputsMap.set(id, input)\n return () => {\n InputsMap.delete(id)\n }\n}\n\nexport const unregisterFocusable = (id: string) => {\n InputsMap.delete(id)\n}\n\nexport const focusFocusable = (id: string, select = false) => {\n const input = InputsMap.get(id)\n if (!input) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn('No input found for id', id)\n }\n return\n }\n if (select || !input.focusAndSelect) {\n input.focus()\n } else {\n input.focusAndSelect()\n }\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAIA,MAAM,YAAY,oBAAI,IAAuB;AAEtC,MAAM,oBAAoB,CAAC,IAAY,UAAqB;AACjE,MAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,QAAI,UAAU,IAAI,EAAE,GAAG;AACrB,cAAQ,KAAK,oCAAoC,IAAI;AAAA,IACvD;AAAA,EACF;AACA,YAAU,IAAI,IAAI,KAAK;AACvB,SAAO,MAAM;AACX,cAAU,OAAO,EAAE;AAAA,EACrB;AACF;AAEO,MAAM,sBAAsB,CAAC,OAAe;AACjD,YAAU,OAAO,EAAE;AACrB;AAEO,MAAM,iBAAiB,CAAC,IAAY,SAAS,UAAU;AAC5D,QAAM,QAAQ,UAAU,IAAI,EAAE;AAC9B,MAAI,CAAC,OAAO;AACV,QAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,cAAQ,KAAK,yBAAyB,EAAE;AAAA,IAC1C;AACA;AAAA,EACF;AACA,MAAI,UAAU,CAAC,MAAM,gBAAgB;AACnC,UAAM,MAAM;AAAA,EACd,OAAO;AACL,UAAM,eAAe;AAAA,EACvB;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
var useControllableState_exports = {};
|
|
19
|
+
__export(useControllableState_exports, {
|
|
20
|
+
useControllableState: () => useControllableState
|
|
21
|
+
});
|
|
22
|
+
module.exports = __toCommonJS(useControllableState_exports);
|
|
23
|
+
var import_use_event = require("@tamagui/use-event");
|
|
24
|
+
var import_react = require("react");
|
|
25
|
+
function useControllableState({
|
|
26
|
+
prop,
|
|
27
|
+
defaultProp,
|
|
28
|
+
onChange,
|
|
29
|
+
strategy = "prop-wins",
|
|
30
|
+
preventUpdate
|
|
31
|
+
}) {
|
|
32
|
+
const currentProp = (0, import_react.useRef)(prop);
|
|
33
|
+
const [val, setVal] = (0, import_react.useState)(prop ?? defaultProp);
|
|
34
|
+
const propWins = strategy === "prop-wins";
|
|
35
|
+
if (currentProp.current !== prop && !preventUpdate) {
|
|
36
|
+
currentProp.current = prop;
|
|
37
|
+
setVal((prev) => {
|
|
38
|
+
return getNextStateWithCallback(prev, prop, onChange);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
return [
|
|
42
|
+
val,
|
|
43
|
+
(0, import_use_event.useEvent)((next) => {
|
|
44
|
+
if (preventUpdate)
|
|
45
|
+
return;
|
|
46
|
+
if (propWins && currentProp.current !== void 0) {
|
|
47
|
+
onChange == null ? void 0 : onChange(next);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
setVal((prev) => {
|
|
51
|
+
return getNextStateWithCallback(prev, typeof next === "function" ? next(prev) : next, onChange);
|
|
52
|
+
});
|
|
53
|
+
})
|
|
54
|
+
];
|
|
55
|
+
}
|
|
56
|
+
const getNextStateWithCallback = (prev, next, handleChange) => {
|
|
57
|
+
if (prev === next || next === void 0) {
|
|
58
|
+
return prev;
|
|
59
|
+
}
|
|
60
|
+
handleChange == null ? void 0 : handleChange(next);
|
|
61
|
+
return next;
|
|
62
|
+
};
|
|
63
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
64
|
+
0 && (module.exports = {
|
|
65
|
+
useControllableState
|
|
66
|
+
});
|
|
67
|
+
//# sourceMappingURL=useControllableState.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/useControllableState.ts"],
|
|
4
|
+
"sourcesContent": ["import { useEvent } from '@tamagui/use-event'\nimport React, { useEffect, useRef, useState } from 'react'\n\n// can configure to allow most-recent-wins or prop-wins\n// defaults to prop-wins\n\ntype ChangeCb<T> = ((next: T) => void) | React.Dispatch<React.SetStateAction<T>>\n\nexport function useControllableState<T>({\n prop,\n defaultProp,\n onChange,\n strategy = 'prop-wins',\n preventUpdate,\n}: {\n prop?: T | undefined\n defaultProp: T\n onChange?: ChangeCb<T>\n strategy?: 'prop-wins' | 'most-recent-wins'\n preventUpdate?: boolean\n}): [T, React.Dispatch<React.SetStateAction<T>>] {\n const currentProp = useRef(prop)\n const [val, setVal] = useState(prop ?? defaultProp)\n const propWins = strategy === 'prop-wins'\n\n // TODO can try no useEffect here right? just if()\n if (currentProp.current !== prop && !preventUpdate) {\n currentProp.current = prop\n setVal((prev) => {\n return getNextStateWithCallback(prev, prop, onChange)\n })\n }\n\n return [\n val,\n useEvent((next: unknown) => {\n if (preventUpdate) return\n if (propWins && currentProp.current !== undefined) {\n onChange?.(next as T)\n return\n }\n setVal((prev) => {\n return getNextStateWithCallback(\n prev,\n typeof next === 'function' ? next(prev) : next,\n onChange\n )\n })\n }),\n ]\n}\n\nconst getNextStateWithCallback = (prev: any, next: any, handleChange?: ChangeCb<any>) => {\n if (prev === next || next === undefined) {\n return prev\n }\n handleChange?.(next)\n return next\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAAyB;AACzB,mBAAmD;AAO5C,8BAAiC;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX;AAAA,GAO+C;AAC/C,QAAM,cAAc,yBAAO,IAAI;AAC/B,QAAM,CAAC,KAAK,UAAU,2BAAS,QAAQ,WAAW;AAClD,QAAM,WAAW,aAAa;AAG9B,MAAI,YAAY,YAAY,QAAQ,CAAC,eAAe;AAClD,gBAAY,UAAU;AACtB,WAAO,CAAC,SAAS;AACf,aAAO,yBAAyB,MAAM,MAAM,QAAQ;AAAA,IACtD,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL;AAAA,IACA,+BAAS,CAAC,SAAkB;AAC1B,UAAI;AAAe;AACnB,UAAI,YAAY,YAAY,YAAY,QAAW;AACjD,6CAAW;AACX;AAAA,MACF;AACA,aAAO,CAAC,SAAS;AACf,eAAO,yBACL,MACA,OAAO,SAAS,aAAa,KAAK,IAAI,IAAI,MAC1C,QACF;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AACF;AAEA,MAAM,2BAA2B,CAAC,MAAW,MAAW,iBAAiC;AACvF,MAAI,SAAS,QAAQ,SAAS,QAAW;AACvC,WAAO;AAAA,EACT;AACA,+CAAe;AACf,SAAO;AACT;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=focusable.js.map
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __spreadValues = (a, b) => {
|
|
9
|
+
for (var prop in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop))
|
|
11
|
+
__defNormalProp(a, prop, b[prop]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
import { composeRefs } from "@tamagui/compose-refs";
|
|
21
|
+
import { isTamaguiComponent } from "@tamagui/core";
|
|
22
|
+
import React, { useRef } from "react";
|
|
23
|
+
import { forwardRef, useCallback, useEffect } from "react";
|
|
24
|
+
import { registerFocusable, unregisterFocusable } from "./registerFocusable";
|
|
25
|
+
function focusableInputHOC(Component) {
|
|
26
|
+
return forwardRef((props, ref) => {
|
|
27
|
+
const isInput = isTamaguiComponent(Component) && Component.staticConfig.isInput;
|
|
28
|
+
const inputValue = useRef(props.value || props.defaultValue || "");
|
|
29
|
+
const inputRef = useCallback((input) => {
|
|
30
|
+
if (!props.id)
|
|
31
|
+
return;
|
|
32
|
+
if (!input)
|
|
33
|
+
return;
|
|
34
|
+
registerFocusable(props.id, __spreadValues({
|
|
35
|
+
focus: input.focus
|
|
36
|
+
}, isInput && {
|
|
37
|
+
focusAndSelect() {
|
|
38
|
+
input.focus();
|
|
39
|
+
if (input.setSelection && typeof inputValue.current === "string") {
|
|
40
|
+
input.setSelection(0, inputValue.current.length);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}));
|
|
44
|
+
}, [props.id]);
|
|
45
|
+
const combinedRefs = composeRefs(ref, inputRef);
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
if (!props.id)
|
|
48
|
+
return;
|
|
49
|
+
return () => {
|
|
50
|
+
unregisterFocusable(props.id);
|
|
51
|
+
};
|
|
52
|
+
}, [props.id]);
|
|
53
|
+
const finalProps = isInput ? __spreadProps(__spreadValues({}, props), {
|
|
54
|
+
onChangeText(value) {
|
|
55
|
+
var _a;
|
|
56
|
+
inputValue.current = value;
|
|
57
|
+
(_a = props.onChangeText) == null ? void 0 : _a.call(props, value);
|
|
58
|
+
}
|
|
59
|
+
}) : props;
|
|
60
|
+
return /* @__PURE__ */ React.createElement(Component, __spreadValues({
|
|
61
|
+
ref: combinedRefs
|
|
62
|
+
}, finalProps));
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
export {
|
|
66
|
+
focusableInputHOC
|
|
67
|
+
};
|
|
68
|
+
//# sourceMappingURL=focusableInputHOC.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/focusableInputHOC.tsx"],
|
|
4
|
+
"sourcesContent": ["import { composeRefs } from '@tamagui/compose-refs'\nimport { isTamaguiComponent } from '@tamagui/core'\nimport React, { useRef } from 'react'\nimport { forwardRef, useCallback, useEffect } from 'react'\n\nimport { registerFocusable, unregisterFocusable } from './registerFocusable'\n\nexport function focusableInputHOC<A extends Function>(Component: A): A {\n return forwardRef(\n (\n props: {\n id?: string\n onChangeText?: (val: string) => void\n value?: string\n defaultValue?: string\n },\n ref\n ) => {\n const isInput = isTamaguiComponent(Component) && Component.staticConfig.isInput\n const inputValue = useRef(props.value || props.defaultValue || '')\n\n const inputRef = useCallback(\n (input) => {\n if (!props.id) return\n if (!input) return\n registerFocusable(props.id, {\n focus: input.focus,\n\n ...(isInput && {\n // react-native doesn't support programmatic .select()\n focusAndSelect() {\n input.focus()\n if (input.setSelection && typeof inputValue.current === 'string') {\n input.setSelection(0, inputValue.current.length)\n }\n },\n }),\n })\n },\n [props.id]\n )\n\n const combinedRefs = composeRefs(ref, inputRef)\n\n useEffect(() => {\n if (!props.id) return\n return () => {\n unregisterFocusable(props.id!)\n }\n }, [props.id])\n\n const finalProps = isInput\n ? {\n ...props,\n onChangeText(value) {\n inputValue.current = value\n props.onChangeText?.(value)\n },\n }\n : props\n\n return <Component ref={combinedRefs} {...finalProps} />\n }\n ) as any\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;AAAA;AACA;AACA;AACA;AAEA;AAEO,2BAA+C,WAAiB;AACrE,SAAO,WACL,CACE,OAMA,QACG;AACH,UAAM,UAAU,mBAAmB,SAAS,KAAK,UAAU,aAAa;AACxE,UAAM,aAAa,OAAO,MAAM,SAAS,MAAM,gBAAgB,EAAE;AAEjE,UAAM,WAAW,YACf,CAAC,UAAU;AACT,UAAI,CAAC,MAAM;AAAI;AACf,UAAI,CAAC;AAAO;AACZ,wBAAkB,MAAM,IAAI;AAAA,QAC1B,OAAO,MAAM;AAAA,SAET,WAAW;AAAA,QAEb,iBAAiB;AACf,gBAAM,MAAM;AACZ,cAAI,MAAM,gBAAgB,OAAO,WAAW,YAAY,UAAU;AAChE,kBAAM,aAAa,GAAG,WAAW,QAAQ,MAAM;AAAA,UACjD;AAAA,QACF;AAAA,MACF,EACD;AAAA,IACH,GACA,CAAC,MAAM,EAAE,CACX;AAEA,UAAM,eAAe,YAAY,KAAK,QAAQ;AAE9C,cAAU,MAAM;AACd,UAAI,CAAC,MAAM;AAAI;AACf,aAAO,MAAM;AACX,4BAAoB,MAAM,EAAG;AAAA,MAC/B;AAAA,IACF,GAAG,CAAC,MAAM,EAAE,CAAC;AAEb,UAAM,aAAa,UACf,iCACK,QADL;AAAA,MAEE,aAAa,OAAO;AAtDhC;AAuDc,mBAAW,UAAU;AACrB,oBAAM,iBAAN,+BAAqB;AAAA,MACvB;AAAA,IACF,KACA;AAEJ,WAAO,oCAAC;AAAA,MAAU,KAAK;AAAA,OAAkB,WAAY;AAAA,EACvD,CACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const registerFocusable = (id, input) => {
|
|
2
|
+
};
|
|
3
|
+
const unregisterFocusable = (id) => {
|
|
4
|
+
};
|
|
5
|
+
const focusFocusable = (id) => {
|
|
6
|
+
};
|
|
7
|
+
export {
|
|
8
|
+
focusFocusable,
|
|
9
|
+
registerFocusable,
|
|
10
|
+
unregisterFocusable
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=registerFocusable.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/registerFocusable.ts"],
|
|
4
|
+
"sourcesContent": ["import { Focusable } from './focusable'\n\nexport const registerFocusable = (id: string, input: Focusable) => {\n // noop focus is handed natively\n}\n\nexport const unregisterFocusable = (id: string) => {\n // noop focus is handed natively\n}\n\nexport const focusFocusable = (id: string) => {\n // noop focus is handed natively\n}\n"],
|
|
5
|
+
"mappings": "AAEO,MAAM,oBAAoB,CAAC,IAAY,UAAqB;AAEnE;AAEO,MAAM,sBAAsB,CAAC,OAAe;AAEnD;AAEO,MAAM,iBAAiB,CAAC,OAAe;AAE9C;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const InputsMap = /* @__PURE__ */ new Map();
|
|
2
|
+
const registerFocusable = (id, input) => {
|
|
3
|
+
if (process.env.NODE_ENV !== "production") {
|
|
4
|
+
if (InputsMap.has(id)) {
|
|
5
|
+
console.warn(`Warning, duplicate ID for input: ${id}`);
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
InputsMap.set(id, input);
|
|
9
|
+
return () => {
|
|
10
|
+
InputsMap.delete(id);
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
const unregisterFocusable = (id) => {
|
|
14
|
+
InputsMap.delete(id);
|
|
15
|
+
};
|
|
16
|
+
const focusFocusable = (id, select = false) => {
|
|
17
|
+
const input = InputsMap.get(id);
|
|
18
|
+
if (!input) {
|
|
19
|
+
if (process.env.NODE_ENV !== "production") {
|
|
20
|
+
console.warn("No input found for id", id);
|
|
21
|
+
}
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
if (select || !input.focusAndSelect) {
|
|
25
|
+
input.focus();
|
|
26
|
+
} else {
|
|
27
|
+
input.focusAndSelect();
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
export {
|
|
31
|
+
focusFocusable,
|
|
32
|
+
registerFocusable,
|
|
33
|
+
unregisterFocusable
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=registerFocusable.native.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/registerFocusable.native.ts"],
|
|
4
|
+
"sourcesContent": ["// used for focusing on native\n\nimport { Focusable } from './focusable'\n\nconst InputsMap = new Map<string, Focusable>()\n\nexport const registerFocusable = (id: string, input: Focusable) => {\n if (process.env.NODE_ENV !== 'production') {\n if (InputsMap.has(id)) {\n console.warn(`Warning, duplicate ID for input: ${id}`)\n }\n }\n InputsMap.set(id, input)\n return () => {\n InputsMap.delete(id)\n }\n}\n\nexport const unregisterFocusable = (id: string) => {\n InputsMap.delete(id)\n}\n\nexport const focusFocusable = (id: string, select = false) => {\n const input = InputsMap.get(id)\n if (!input) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn('No input found for id', id)\n }\n return\n }\n if (select || !input.focusAndSelect) {\n input.focus()\n } else {\n input.focusAndSelect()\n }\n}\n"],
|
|
5
|
+
"mappings": "AAIA,MAAM,YAAY,oBAAI,IAAuB;AAEtC,MAAM,oBAAoB,CAAC,IAAY,UAAqB;AACjE,MAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,QAAI,UAAU,IAAI,EAAE,GAAG;AACrB,cAAQ,KAAK,oCAAoC,IAAI;AAAA,IACvD;AAAA,EACF;AACA,YAAU,IAAI,IAAI,KAAK;AACvB,SAAO,MAAM;AACX,cAAU,OAAO,EAAE;AAAA,EACrB;AACF;AAEO,MAAM,sBAAsB,CAAC,OAAe;AACjD,YAAU,OAAO,EAAE;AACrB;AAEO,MAAM,iBAAiB,CAAC,IAAY,SAAS,UAAU;AAC5D,QAAM,QAAQ,UAAU,IAAI,EAAE;AAC9B,MAAI,CAAC,OAAO;AACV,QAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,cAAQ,KAAK,yBAAyB,EAAE;AAAA,IAC1C;AACA;AAAA,EACF;AACA,MAAI,UAAU,CAAC,MAAM,gBAAgB;AACnC,UAAM,MAAM;AAAA,EACd,OAAO;AACL,UAAM,eAAe;AAAA,EACvB;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { useEvent } from "@tamagui/use-event";
|
|
2
|
+
import { useRef, useState } from "react";
|
|
3
|
+
function useControllableState({
|
|
4
|
+
prop,
|
|
5
|
+
defaultProp,
|
|
6
|
+
onChange,
|
|
7
|
+
strategy = "prop-wins",
|
|
8
|
+
preventUpdate
|
|
9
|
+
}) {
|
|
10
|
+
const currentProp = useRef(prop);
|
|
11
|
+
const [val, setVal] = useState(prop ?? defaultProp);
|
|
12
|
+
const propWins = strategy === "prop-wins";
|
|
13
|
+
if (currentProp.current !== prop && !preventUpdate) {
|
|
14
|
+
currentProp.current = prop;
|
|
15
|
+
setVal((prev) => {
|
|
16
|
+
return getNextStateWithCallback(prev, prop, onChange);
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
return [
|
|
20
|
+
val,
|
|
21
|
+
useEvent((next) => {
|
|
22
|
+
if (preventUpdate)
|
|
23
|
+
return;
|
|
24
|
+
if (propWins && currentProp.current !== void 0) {
|
|
25
|
+
onChange == null ? void 0 : onChange(next);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
setVal((prev) => {
|
|
29
|
+
return getNextStateWithCallback(prev, typeof next === "function" ? next(prev) : next, onChange);
|
|
30
|
+
});
|
|
31
|
+
})
|
|
32
|
+
];
|
|
33
|
+
}
|
|
34
|
+
const getNextStateWithCallback = (prev, next, handleChange) => {
|
|
35
|
+
if (prev === next || next === void 0) {
|
|
36
|
+
return prev;
|
|
37
|
+
}
|
|
38
|
+
handleChange == null ? void 0 : handleChange(next);
|
|
39
|
+
return next;
|
|
40
|
+
};
|
|
41
|
+
export {
|
|
42
|
+
useControllableState
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=useControllableState.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/useControllableState.ts"],
|
|
4
|
+
"sourcesContent": ["import { useEvent } from '@tamagui/use-event'\nimport React, { useEffect, useRef, useState } from 'react'\n\n// can configure to allow most-recent-wins or prop-wins\n// defaults to prop-wins\n\ntype ChangeCb<T> = ((next: T) => void) | React.Dispatch<React.SetStateAction<T>>\n\nexport function useControllableState<T>({\n prop,\n defaultProp,\n onChange,\n strategy = 'prop-wins',\n preventUpdate,\n}: {\n prop?: T | undefined\n defaultProp: T\n onChange?: ChangeCb<T>\n strategy?: 'prop-wins' | 'most-recent-wins'\n preventUpdate?: boolean\n}): [T, React.Dispatch<React.SetStateAction<T>>] {\n const currentProp = useRef(prop)\n const [val, setVal] = useState(prop ?? defaultProp)\n const propWins = strategy === 'prop-wins'\n\n // TODO can try no useEffect here right? just if()\n if (currentProp.current !== prop && !preventUpdate) {\n currentProp.current = prop\n setVal((prev) => {\n return getNextStateWithCallback(prev, prop, onChange)\n })\n }\n\n return [\n val,\n useEvent((next: unknown) => {\n if (preventUpdate) return\n if (propWins && currentProp.current !== undefined) {\n onChange?.(next as T)\n return\n }\n setVal((prev) => {\n return getNextStateWithCallback(\n prev,\n typeof next === 'function' ? next(prev) : next,\n onChange\n )\n })\n }),\n ]\n}\n\nconst getNextStateWithCallback = (prev: any, next: any, handleChange?: ChangeCb<any>) => {\n if (prev === next || next === undefined) {\n return prev\n }\n handleChange?.(next)\n return next\n}\n"],
|
|
5
|
+
"mappings": "AAAA;AACA;AAOO,8BAAiC;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX;AAAA,GAO+C;AAC/C,QAAM,cAAc,OAAO,IAAI;AAC/B,QAAM,CAAC,KAAK,UAAU,SAAS,QAAQ,WAAW;AAClD,QAAM,WAAW,aAAa;AAG9B,MAAI,YAAY,YAAY,QAAQ,CAAC,eAAe;AAClD,gBAAY,UAAU;AACtB,WAAO,CAAC,SAAS;AACf,aAAO,yBAAyB,MAAM,MAAM,QAAQ;AAAA,IACtD,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL;AAAA,IACA,SAAS,CAAC,SAAkB;AAC1B,UAAI;AAAe;AACnB,UAAI,YAAY,YAAY,YAAY,QAAW;AACjD,6CAAW;AACX;AAAA,MACF;AACA,aAAO,CAAC,SAAS;AACf,eAAO,yBACL,MACA,OAAO,SAAS,aAAa,KAAK,IAAI,IAAI,MAC1C,QACF;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AACF;AAEA,MAAM,2BAA2B,CAAC,MAAW,MAAW,iBAAiC;AACvF,MAAI,SAAS,QAAQ,SAAS,QAAW;AACvC,WAAO;AAAA,EACT;AACA,+CAAe;AACf,SAAO;AACT;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=focusable.js.map
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { composeRefs } from "@tamagui/compose-refs";
|
|
2
|
+
import { isTamaguiComponent } from "@tamagui/core";
|
|
3
|
+
import { useRef } from "react";
|
|
4
|
+
import { forwardRef, useCallback, useEffect } from "react";
|
|
5
|
+
import { registerFocusable, unregisterFocusable } from "./registerFocusable";
|
|
6
|
+
function focusableInputHOC(Component) {
|
|
7
|
+
return forwardRef((props, ref) => {
|
|
8
|
+
const isInput = isTamaguiComponent(Component) && Component.staticConfig.isInput;
|
|
9
|
+
const inputValue = useRef(props.value || props.defaultValue || "");
|
|
10
|
+
const inputRef = useCallback((input) => {
|
|
11
|
+
if (!props.id)
|
|
12
|
+
return;
|
|
13
|
+
if (!input)
|
|
14
|
+
return;
|
|
15
|
+
registerFocusable(props.id, {
|
|
16
|
+
focus: input.focus,
|
|
17
|
+
...isInput && {
|
|
18
|
+
focusAndSelect() {
|
|
19
|
+
input.focus();
|
|
20
|
+
if (input.setSelection && typeof inputValue.current === "string") {
|
|
21
|
+
input.setSelection(0, inputValue.current.length);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}, [props.id]);
|
|
27
|
+
const combinedRefs = composeRefs(ref, inputRef);
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
if (!props.id)
|
|
30
|
+
return;
|
|
31
|
+
return () => {
|
|
32
|
+
unregisterFocusable(props.id);
|
|
33
|
+
};
|
|
34
|
+
}, [props.id]);
|
|
35
|
+
const finalProps = isInput ? {
|
|
36
|
+
...props,
|
|
37
|
+
onChangeText(value) {
|
|
38
|
+
var _a;
|
|
39
|
+
inputValue.current = value;
|
|
40
|
+
(_a = props.onChangeText) == null ? void 0 : _a.call(props, value);
|
|
41
|
+
}
|
|
42
|
+
} : props;
|
|
43
|
+
return <Component ref={combinedRefs} {...finalProps} />;
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
export {
|
|
47
|
+
focusableInputHOC
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=focusableInputHOC.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/focusableInputHOC.tsx"],
|
|
4
|
+
"sourcesContent": ["import { composeRefs } from '@tamagui/compose-refs'\nimport { isTamaguiComponent } from '@tamagui/core'\nimport React, { useRef } from 'react'\nimport { forwardRef, useCallback, useEffect } from 'react'\n\nimport { registerFocusable, unregisterFocusable } from './registerFocusable'\n\nexport function focusableInputHOC<A extends Function>(Component: A): A {\n return forwardRef(\n (\n props: {\n id?: string\n onChangeText?: (val: string) => void\n value?: string\n defaultValue?: string\n },\n ref\n ) => {\n const isInput = isTamaguiComponent(Component) && Component.staticConfig.isInput\n const inputValue = useRef(props.value || props.defaultValue || '')\n\n const inputRef = useCallback(\n (input) => {\n if (!props.id) return\n if (!input) return\n registerFocusable(props.id, {\n focus: input.focus,\n\n ...(isInput && {\n // react-native doesn't support programmatic .select()\n focusAndSelect() {\n input.focus()\n if (input.setSelection && typeof inputValue.current === 'string') {\n input.setSelection(0, inputValue.current.length)\n }\n },\n }),\n })\n },\n [props.id]\n )\n\n const combinedRefs = composeRefs(ref, inputRef)\n\n useEffect(() => {\n if (!props.id) return\n return () => {\n unregisterFocusable(props.id!)\n }\n }, [props.id])\n\n const finalProps = isInput\n ? {\n ...props,\n onChangeText(value) {\n inputValue.current = value\n props.onChangeText?.(value)\n },\n }\n : props\n\n return <Component ref={combinedRefs} {...finalProps} />\n }\n ) as any\n}\n"],
|
|
5
|
+
"mappings": "AAAA;AACA;AACA;AACA;AAEA;AAEO,2BAA+C,WAAiB;AACrE,SAAO,WACL,CACE,OAMA,QACG;AACH,UAAM,UAAU,mBAAmB,SAAS,KAAK,UAAU,aAAa;AACxE,UAAM,aAAa,OAAO,MAAM,SAAS,MAAM,gBAAgB,EAAE;AAEjE,UAAM,WAAW,YACf,CAAC,UAAU;AACT,UAAI,CAAC,MAAM;AAAI;AACf,UAAI,CAAC;AAAO;AACZ,wBAAkB,MAAM,IAAI;AAAA,QAC1B,OAAO,MAAM;AAAA,QAEb,GAAI,WAAW;AAAA,UAEb,iBAAiB;AACf,kBAAM,MAAM;AACZ,gBAAI,MAAM,gBAAgB,OAAO,WAAW,YAAY,UAAU;AAChE,oBAAM,aAAa,GAAG,WAAW,QAAQ,MAAM;AAAA,YACjD;AAAA,UACF;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH,GACA,CAAC,MAAM,EAAE,CACX;AAEA,UAAM,eAAe,YAAY,KAAK,QAAQ;AAE9C,cAAU,MAAM;AACd,UAAI,CAAC,MAAM;AAAI;AACf,aAAO,MAAM;AACX,4BAAoB,MAAM,EAAG;AAAA,MAC/B;AAAA,IACF,GAAG,CAAC,MAAM,EAAE,CAAC;AAEb,UAAM,aAAa,UACf;AAAA,MACE,GAAG;AAAA,MACH,aAAa,OAAO;AAtDhC;AAuDc,mBAAW,UAAU;AACrB,oBAAM,iBAAN,+BAAqB;AAAA,MACvB;AAAA,IACF,IACA;AAEJ,WAAO,CAAC,UAAU,KAAK,kBAAkB,YAAY;AAAA,EACvD,CACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const registerFocusable = (id, input) => {
|
|
2
|
+
};
|
|
3
|
+
const unregisterFocusable = (id) => {
|
|
4
|
+
};
|
|
5
|
+
const focusFocusable = (id) => {
|
|
6
|
+
};
|
|
7
|
+
export {
|
|
8
|
+
focusFocusable,
|
|
9
|
+
registerFocusable,
|
|
10
|
+
unregisterFocusable
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=registerFocusable.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/registerFocusable.ts"],
|
|
4
|
+
"sourcesContent": ["import { Focusable } from './focusable'\n\nexport const registerFocusable = (id: string, input: Focusable) => {\n // noop focus is handed natively\n}\n\nexport const unregisterFocusable = (id: string) => {\n // noop focus is handed natively\n}\n\nexport const focusFocusable = (id: string) => {\n // noop focus is handed natively\n}\n"],
|
|
5
|
+
"mappings": "AAEO,MAAM,oBAAoB,CAAC,IAAY,UAAqB;AAEnE;AAEO,MAAM,sBAAsB,CAAC,OAAe;AAEnD;AAEO,MAAM,iBAAiB,CAAC,OAAe;AAE9C;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const InputsMap = /* @__PURE__ */ new Map();
|
|
2
|
+
const registerFocusable = (id, input) => {
|
|
3
|
+
if (process.env.NODE_ENV !== "production") {
|
|
4
|
+
if (InputsMap.has(id)) {
|
|
5
|
+
console.warn(`Warning, duplicate ID for input: ${id}`);
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
InputsMap.set(id, input);
|
|
9
|
+
return () => {
|
|
10
|
+
InputsMap.delete(id);
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
const unregisterFocusable = (id) => {
|
|
14
|
+
InputsMap.delete(id);
|
|
15
|
+
};
|
|
16
|
+
const focusFocusable = (id, select = false) => {
|
|
17
|
+
const input = InputsMap.get(id);
|
|
18
|
+
if (!input) {
|
|
19
|
+
if (process.env.NODE_ENV !== "production") {
|
|
20
|
+
console.warn("No input found for id", id);
|
|
21
|
+
}
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
if (select || !input.focusAndSelect) {
|
|
25
|
+
input.focus();
|
|
26
|
+
} else {
|
|
27
|
+
input.focusAndSelect();
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
export {
|
|
31
|
+
focusFocusable,
|
|
32
|
+
registerFocusable,
|
|
33
|
+
unregisterFocusable
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=registerFocusable.native.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/registerFocusable.native.ts"],
|
|
4
|
+
"sourcesContent": ["// used for focusing on native\n\nimport { Focusable } from './focusable'\n\nconst InputsMap = new Map<string, Focusable>()\n\nexport const registerFocusable = (id: string, input: Focusable) => {\n if (process.env.NODE_ENV !== 'production') {\n if (InputsMap.has(id)) {\n console.warn(`Warning, duplicate ID for input: ${id}`)\n }\n }\n InputsMap.set(id, input)\n return () => {\n InputsMap.delete(id)\n }\n}\n\nexport const unregisterFocusable = (id: string) => {\n InputsMap.delete(id)\n}\n\nexport const focusFocusable = (id: string, select = false) => {\n const input = InputsMap.get(id)\n if (!input) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn('No input found for id', id)\n }\n return\n }\n if (select || !input.focusAndSelect) {\n input.focus()\n } else {\n input.focusAndSelect()\n }\n}\n"],
|
|
5
|
+
"mappings": "AAIA,MAAM,YAAY,oBAAI,IAAuB;AAEtC,MAAM,oBAAoB,CAAC,IAAY,UAAqB;AACjE,MAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,QAAI,UAAU,IAAI,EAAE,GAAG;AACrB,cAAQ,KAAK,oCAAoC,IAAI;AAAA,IACvD;AAAA,EACF;AACA,YAAU,IAAI,IAAI,KAAK;AACvB,SAAO,MAAM;AACX,cAAU,OAAO,EAAE;AAAA,EACrB;AACF;AAEO,MAAM,sBAAsB,CAAC,OAAe;AACjD,YAAU,OAAO,EAAE;AACrB;AAEO,MAAM,iBAAiB,CAAC,IAAY,SAAS,UAAU;AAC5D,QAAM,QAAQ,UAAU,IAAI,EAAE;AAC9B,MAAI,CAAC,OAAO;AACV,QAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,cAAQ,KAAK,yBAAyB,EAAE;AAAA,IAC1C;AACA;AAAA,EACF;AACA,MAAI,UAAU,CAAC,MAAM,gBAAgB;AACnC,UAAM,MAAM;AAAA,EACd,OAAO;AACL,UAAM,eAAe;AAAA,EACvB;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { useEvent } from "@tamagui/use-event";
|
|
2
|
+
import { useRef, useState } from "react";
|
|
3
|
+
function useControllableState({
|
|
4
|
+
prop,
|
|
5
|
+
defaultProp,
|
|
6
|
+
onChange,
|
|
7
|
+
strategy = "prop-wins",
|
|
8
|
+
preventUpdate
|
|
9
|
+
}) {
|
|
10
|
+
const currentProp = useRef(prop);
|
|
11
|
+
const [val, setVal] = useState(prop != null ? prop : defaultProp);
|
|
12
|
+
const propWins = strategy === "prop-wins";
|
|
13
|
+
if (currentProp.current !== prop && !preventUpdate) {
|
|
14
|
+
currentProp.current = prop;
|
|
15
|
+
setVal((prev) => {
|
|
16
|
+
return getNextStateWithCallback(prev, prop, onChange);
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
return [
|
|
20
|
+
val,
|
|
21
|
+
useEvent((next) => {
|
|
22
|
+
if (preventUpdate)
|
|
23
|
+
return;
|
|
24
|
+
if (propWins && currentProp.current !== void 0) {
|
|
25
|
+
onChange == null ? void 0 : onChange(next);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
setVal((prev) => {
|
|
29
|
+
return getNextStateWithCallback(prev, typeof next === "function" ? next(prev) : next, onChange);
|
|
30
|
+
});
|
|
31
|
+
})
|
|
32
|
+
];
|
|
33
|
+
}
|
|
34
|
+
const getNextStateWithCallback = (prev, next, handleChange) => {
|
|
35
|
+
if (prev === next || next === void 0) {
|
|
36
|
+
return prev;
|
|
37
|
+
}
|
|
38
|
+
handleChange == null ? void 0 : handleChange(next);
|
|
39
|
+
return next;
|
|
40
|
+
};
|
|
41
|
+
export {
|
|
42
|
+
useControllableState
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=useControllableState.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/useControllableState.ts"],
|
|
4
|
+
"sourcesContent": ["import { useEvent } from '@tamagui/use-event'\nimport React, { useEffect, useRef, useState } from 'react'\n\n// can configure to allow most-recent-wins or prop-wins\n// defaults to prop-wins\n\ntype ChangeCb<T> = ((next: T) => void) | React.Dispatch<React.SetStateAction<T>>\n\nexport function useControllableState<T>({\n prop,\n defaultProp,\n onChange,\n strategy = 'prop-wins',\n preventUpdate,\n}: {\n prop?: T | undefined\n defaultProp: T\n onChange?: ChangeCb<T>\n strategy?: 'prop-wins' | 'most-recent-wins'\n preventUpdate?: boolean\n}): [T, React.Dispatch<React.SetStateAction<T>>] {\n const currentProp = useRef(prop)\n const [val, setVal] = useState(prop ?? defaultProp)\n const propWins = strategy === 'prop-wins'\n\n // TODO can try no useEffect here right? just if()\n if (currentProp.current !== prop && !preventUpdate) {\n currentProp.current = prop\n setVal((prev) => {\n return getNextStateWithCallback(prev, prop, onChange)\n })\n }\n\n return [\n val,\n useEvent((next: unknown) => {\n if (preventUpdate) return\n if (propWins && currentProp.current !== undefined) {\n onChange?.(next as T)\n return\n }\n setVal((prev) => {\n return getNextStateWithCallback(\n prev,\n typeof next === 'function' ? next(prev) : next,\n onChange\n )\n })\n }),\n ]\n}\n\nconst getNextStateWithCallback = (prev: any, next: any, handleChange?: ChangeCb<any>) => {\n if (prev === next || next === undefined) {\n return prev\n }\n handleChange?.(next)\n return next\n}\n"],
|
|
5
|
+
"mappings": "AAAA;AACA;AAOO,8BAAiC;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX;AAAA,GAO+C;AAC/C,QAAM,cAAc,OAAO,IAAI;AAC/B,QAAM,CAAC,KAAK,UAAU,SAAS,sBAAQ,WAAW;AAClD,QAAM,WAAW,aAAa;AAG9B,MAAI,YAAY,YAAY,QAAQ,CAAC,eAAe;AAClD,gBAAY,UAAU;AACtB,WAAO,CAAC,SAAS;AACf,aAAO,yBAAyB,MAAM,MAAM,QAAQ;AAAA,IACtD,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL;AAAA,IACA,SAAS,CAAC,SAAkB;AAC1B,UAAI;AAAe;AACnB,UAAI,YAAY,YAAY,YAAY,QAAW;AACjD,6CAAW;AACX;AAAA,MACF;AACA,aAAO,CAAC,SAAS;AACf,eAAO,yBACL,MACA,OAAO,SAAS,aAAa,KAAK,IAAI,IAAI,MAC1C,QACF;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AACF;AAEA,MAAM,2BAA2B,CAAC,MAAW,MAAW,iBAAiC;AACvF,MAAI,SAAS,QAAQ,SAAS,QAAW;AACvC,WAAO;AAAA,EACT;AACA,+CAAe;AACf,SAAO;AACT;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tamagui/focusable",
|
|
3
|
+
"version": "1.0.1-beta.103",
|
|
4
|
+
"sideEffects": false,
|
|
5
|
+
"source": "src/index.ts",
|
|
6
|
+
"types": "./types/index.d.ts",
|
|
7
|
+
"main": "dist/cjs",
|
|
8
|
+
"module": "dist/esm",
|
|
9
|
+
"module:jsx": "dist/jsx",
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"files": [
|
|
12
|
+
"src",
|
|
13
|
+
"types",
|
|
14
|
+
"dist"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tamagui-build",
|
|
18
|
+
"watch": "tamagui-build --watch",
|
|
19
|
+
"clean": "tamagui-build clean",
|
|
20
|
+
"clean:build": "tamagui-build clean:build"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@tamagui/compose-refs": "^1.0.1-beta.103",
|
|
24
|
+
"@tamagui/core": "^1.0.1-beta.103"
|
|
25
|
+
},
|
|
26
|
+
"peerDependencies": {
|
|
27
|
+
"react": "*",
|
|
28
|
+
"react-dom": "*"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@tamagui/build": "^1.0.1-beta.103",
|
|
32
|
+
"react": "*",
|
|
33
|
+
"react-dom": "*"
|
|
34
|
+
},
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"access": "public"
|
|
37
|
+
}
|
|
38
|
+
}
|
package/src/focusable.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type Focusable = { focus: Function; focusAndSelect?: Function }
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { composeRefs } from '@tamagui/compose-refs'
|
|
2
|
+
import { isTamaguiComponent } from '@tamagui/core'
|
|
3
|
+
import React, { useRef } from 'react'
|
|
4
|
+
import { forwardRef, useCallback, useEffect } from 'react'
|
|
5
|
+
|
|
6
|
+
import { registerFocusable, unregisterFocusable } from './registerFocusable'
|
|
7
|
+
|
|
8
|
+
export function focusableInputHOC<A extends Function>(Component: A): A {
|
|
9
|
+
return forwardRef(
|
|
10
|
+
(
|
|
11
|
+
props: {
|
|
12
|
+
id?: string
|
|
13
|
+
onChangeText?: (val: string) => void
|
|
14
|
+
value?: string
|
|
15
|
+
defaultValue?: string
|
|
16
|
+
},
|
|
17
|
+
ref
|
|
18
|
+
) => {
|
|
19
|
+
const isInput = isTamaguiComponent(Component) && Component.staticConfig.isInput
|
|
20
|
+
const inputValue = useRef(props.value || props.defaultValue || '')
|
|
21
|
+
|
|
22
|
+
const inputRef = useCallback(
|
|
23
|
+
(input) => {
|
|
24
|
+
if (!props.id) return
|
|
25
|
+
if (!input) return
|
|
26
|
+
registerFocusable(props.id, {
|
|
27
|
+
focus: input.focus,
|
|
28
|
+
|
|
29
|
+
...(isInput && {
|
|
30
|
+
// react-native doesn't support programmatic .select()
|
|
31
|
+
focusAndSelect() {
|
|
32
|
+
input.focus()
|
|
33
|
+
if (input.setSelection && typeof inputValue.current === 'string') {
|
|
34
|
+
input.setSelection(0, inputValue.current.length)
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
}),
|
|
38
|
+
})
|
|
39
|
+
},
|
|
40
|
+
[props.id]
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
const combinedRefs = composeRefs(ref, inputRef)
|
|
44
|
+
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
if (!props.id) return
|
|
47
|
+
return () => {
|
|
48
|
+
unregisterFocusable(props.id!)
|
|
49
|
+
}
|
|
50
|
+
}, [props.id])
|
|
51
|
+
|
|
52
|
+
const finalProps = isInput
|
|
53
|
+
? {
|
|
54
|
+
...props,
|
|
55
|
+
onChangeText(value) {
|
|
56
|
+
inputValue.current = value
|
|
57
|
+
props.onChangeText?.(value)
|
|
58
|
+
},
|
|
59
|
+
}
|
|
60
|
+
: props
|
|
61
|
+
|
|
62
|
+
return <Component ref={combinedRefs} {...finalProps} />
|
|
63
|
+
}
|
|
64
|
+
) as any
|
|
65
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// used for focusing on native
|
|
2
|
+
|
|
3
|
+
import { Focusable } from './focusable'
|
|
4
|
+
|
|
5
|
+
const InputsMap = new Map<string, Focusable>()
|
|
6
|
+
|
|
7
|
+
export const registerFocusable = (id: string, input: Focusable) => {
|
|
8
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
9
|
+
if (InputsMap.has(id)) {
|
|
10
|
+
console.warn(`Warning, duplicate ID for input: ${id}`)
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
InputsMap.set(id, input)
|
|
14
|
+
return () => {
|
|
15
|
+
InputsMap.delete(id)
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const unregisterFocusable = (id: string) => {
|
|
20
|
+
InputsMap.delete(id)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const focusFocusable = (id: string, select = false) => {
|
|
24
|
+
const input = InputsMap.get(id)
|
|
25
|
+
if (!input) {
|
|
26
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
27
|
+
console.warn('No input found for id', id)
|
|
28
|
+
}
|
|
29
|
+
return
|
|
30
|
+
}
|
|
31
|
+
if (select || !input.focusAndSelect) {
|
|
32
|
+
input.focus()
|
|
33
|
+
} else {
|
|
34
|
+
input.focusAndSelect()
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Focusable } from './focusable'
|
|
2
|
+
|
|
3
|
+
export const registerFocusable = (id: string, input: Focusable) => {
|
|
4
|
+
// noop focus is handed natively
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export const unregisterFocusable = (id: string) => {
|
|
8
|
+
// noop focus is handed natively
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const focusFocusable = (id: string) => {
|
|
12
|
+
// noop focus is handed natively
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"focusable.d.ts","sourceRoot":"","sources":["../src/focusable.ts"],"names":[],"mappings":"AAAA,oBAAY,SAAS,GAAG;IAAE,KAAK,EAAE,QAAQ,CAAC;IAAC,cAAc,CAAC,EAAE,QAAQ,CAAA;CAAE,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"focusableInputHOC.d.ts","sourceRoot":"","sources":["../src/focusableInputHOC.tsx"],"names":[],"mappings":"AAOA,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,QAAQ,EAAE,SAAS,EAAE,CAAC,GAAG,CAAC,CAyDrE"}
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,aAAa,CAAA"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Focusable } from './focusable';
|
|
2
|
+
export declare const registerFocusable: (id: string, input: Focusable) => void;
|
|
3
|
+
export declare const unregisterFocusable: (id: string) => void;
|
|
4
|
+
export declare const focusFocusable: (id: string) => void;
|
|
5
|
+
//# sourceMappingURL=registerFocusable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registerFocusable.d.ts","sourceRoot":"","sources":["../src/registerFocusable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAEvC,eAAO,MAAM,iBAAiB,OAAQ,MAAM,SAAS,SAAS,SAE7D,CAAA;AAED,eAAO,MAAM,mBAAmB,OAAQ,MAAM,SAE7C,CAAA;AAED,eAAO,MAAM,cAAc,OAAQ,MAAM,SAExC,CAAA"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Focusable } from './focusable';
|
|
2
|
+
export declare const registerFocusable: (id: string, input: Focusable) => () => void;
|
|
3
|
+
export declare const unregisterFocusable: (id: string) => void;
|
|
4
|
+
export declare const focusFocusable: (id: string, select?: boolean) => void;
|
|
5
|
+
//# sourceMappingURL=registerFocusable.native.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registerFocusable.native.d.ts","sourceRoot":"","sources":["../src/registerFocusable.native.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAIvC,eAAO,MAAM,iBAAiB,OAAQ,MAAM,SAAS,SAAS,eAU7D,CAAA;AAED,eAAO,MAAM,mBAAmB,OAAQ,MAAM,SAE7C,CAAA;AAED,eAAO,MAAM,cAAc,OAAQ,MAAM,2BAaxC,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
declare type ChangeCb<T> = ((next: T) => void) | React.Dispatch<React.SetStateAction<T>>;
|
|
3
|
+
export declare function useControllableState<T>({ prop, defaultProp, onChange, strategy, preventUpdate, }: {
|
|
4
|
+
prop?: T | undefined;
|
|
5
|
+
defaultProp: T;
|
|
6
|
+
onChange?: ChangeCb<T>;
|
|
7
|
+
strategy?: 'prop-wins' | 'most-recent-wins';
|
|
8
|
+
preventUpdate?: boolean;
|
|
9
|
+
}): [T, React.Dispatch<React.SetStateAction<T>>];
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=useControllableState.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useControllableState.d.ts","sourceRoot":"","sources":["../src/useControllableState.ts"],"names":[],"mappings":"AACA,OAAO,KAAsC,MAAM,OAAO,CAAA;AAK1D,aAAK,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAA;AAEhF,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,EACtC,IAAI,EACJ,WAAW,EACX,QAAQ,EACR,QAAsB,EACtB,aAAa,GACd,EAAE;IACD,IAAI,CAAC,EAAE,CAAC,GAAG,SAAS,CAAA;IACpB,WAAW,EAAE,CAAC,CAAA;IACd,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAA;IACtB,QAAQ,CAAC,EAAE,WAAW,GAAG,kBAAkB,CAAA;IAC3C,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CA8B/C"}
|