@scripso-homepad/ui 0.4.18 → 0.4.20
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/{chunk-U7OSCJKA.js → chunk-F7NV3HPU.js} +60 -20
- package/dist/chunk-F7NV3HPU.js.map +1 -0
- package/dist/index.cjs +126 -63
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +70 -47
- package/dist/index.js.map +1 -1
- package/dist/web/index.cjs +59 -19
- package/dist/web/index.cjs.map +1 -1
- package/dist/web/index.css +1 -6
- package/dist/web/index.css.map +1 -1
- package/dist/web/index.js +2 -2
- package/dist/web/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Button.tsx +1 -1
- package/src/components/Input.tsx +43 -2
- package/src/components/PhoneInput.tsx +11 -0
- package/src/components/Select.tsx +28 -16
- package/src/theme/input.ts +23 -13
- package/src/web/components/TableActionsMenu.tsx +1 -1
- package/src/web/components/drawer-scroll.css +1 -7
- package/dist/chunk-U7OSCJKA.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -460,7 +460,8 @@ var styles = reactNative.StyleSheet.create({
|
|
|
460
460
|
justifyContent: "center"
|
|
461
461
|
},
|
|
462
462
|
withIcon: {
|
|
463
|
-
justifyContent: "space-between"
|
|
463
|
+
justifyContent: "space-between",
|
|
464
|
+
gap: 24
|
|
464
465
|
},
|
|
465
466
|
disabled: {
|
|
466
467
|
opacity: 0.6
|
|
@@ -474,8 +475,7 @@ var styles = reactNative.StyleSheet.create({
|
|
|
474
475
|
},
|
|
475
476
|
labelWithIcon: {
|
|
476
477
|
flex: 1,
|
|
477
|
-
flexShrink: 1
|
|
478
|
-
marginRight: 8
|
|
478
|
+
flexShrink: 1
|
|
479
479
|
},
|
|
480
480
|
iconContainer: {
|
|
481
481
|
alignItems: "center",
|
|
@@ -532,12 +532,14 @@ function EyeOffIcon({
|
|
|
532
532
|
}
|
|
533
533
|
) });
|
|
534
534
|
}
|
|
535
|
-
var INPUT_HEIGHT =
|
|
535
|
+
var INPUT_HEIGHT = 56;
|
|
536
536
|
var INPUT_ICON_SIZE = 20;
|
|
537
537
|
var INPUT_ICON_GAP = 10;
|
|
538
538
|
var INPUT_OUTLINE_WIDTH = 2;
|
|
539
|
-
var INPUT_TEXT_LINE_HEIGHT =
|
|
539
|
+
var INPUT_TEXT_LINE_HEIGHT = 20;
|
|
540
540
|
var INPUT_WEB_VERTICAL_PADDING = 14;
|
|
541
|
+
var INPUT_VERTICAL_PADDING = 14;
|
|
542
|
+
var INPUT_HORIZONTAL_PADDING = 16;
|
|
541
543
|
function resolveInputVisualState({
|
|
542
544
|
focused = false,
|
|
543
545
|
error = false,
|
|
@@ -556,8 +558,7 @@ function createOutlineStyle(ringColor) {
|
|
|
556
558
|
padding: 0,
|
|
557
559
|
backgroundColor: colors.transparent,
|
|
558
560
|
width: "100%",
|
|
559
|
-
alignSelf: "stretch"
|
|
560
|
-
...reactNative.Platform.OS !== "web" ? { overflow: "hidden" } : null
|
|
561
|
+
alignSelf: "stretch"
|
|
561
562
|
};
|
|
562
563
|
}
|
|
563
564
|
var defaultOutline = {
|
|
@@ -567,13 +568,11 @@ var defaultOutline = {
|
|
|
567
568
|
padding: 0,
|
|
568
569
|
backgroundColor: colors.transparent,
|
|
569
570
|
width: "100%",
|
|
570
|
-
alignSelf: "stretch"
|
|
571
|
-
...reactNative.Platform.OS !== "web" ? { overflow: "hidden" } : null
|
|
571
|
+
alignSelf: "stretch"
|
|
572
572
|
};
|
|
573
573
|
function getInputFieldStyles(state) {
|
|
574
574
|
const containerBase = {
|
|
575
|
-
borderRadius: radii.lg
|
|
576
|
-
...reactNative.Platform.OS !== "web" ? { overflow: "hidden" } : null
|
|
575
|
+
borderRadius: radii.lg
|
|
577
576
|
};
|
|
578
577
|
switch (state) {
|
|
579
578
|
case "disabled":
|
|
@@ -636,12 +635,15 @@ var inputFieldMetrics = reactNative.StyleSheet.create({
|
|
|
636
635
|
alignItems: "center",
|
|
637
636
|
height: INPUT_HEIGHT,
|
|
638
637
|
borderRadius: radii.lg,
|
|
639
|
-
|
|
638
|
+
paddingHorizontal: INPUT_HORIZONTAL_PADDING,
|
|
639
|
+
paddingVertical: INPUT_VERTICAL_PADDING,
|
|
640
640
|
gap: INPUT_ICON_GAP,
|
|
641
|
+
// Do not clip glyph ascenders (Armenian / tall fonts).
|
|
642
|
+
overflow: "visible",
|
|
641
643
|
...reactNative.Platform.OS === "web" ? {
|
|
642
644
|
boxSizing: "border-box",
|
|
643
645
|
paddingVertical: INPUT_WEB_VERTICAL_PADDING,
|
|
644
|
-
paddingHorizontal:
|
|
646
|
+
paddingHorizontal: INPUT_HORIZONTAL_PADDING
|
|
645
647
|
} : null
|
|
646
648
|
},
|
|
647
649
|
input: {
|
|
@@ -656,8 +658,7 @@ var inputFieldMetrics = reactNative.StyleSheet.create({
|
|
|
656
658
|
margin: 0,
|
|
657
659
|
borderWidth: 0,
|
|
658
660
|
backgroundColor: colors.transparent,
|
|
659
|
-
|
|
660
|
-
...reactNative.Platform.OS === "ios" ? { lineHeight: INPUT_TEXT_LINE_HEIGHT, paddingVertical: 2 } : null,
|
|
661
|
+
// Leave lineHeight unset so platform font metrics keep placeholder tops visible.
|
|
661
662
|
...reactNative.Platform.OS === "web" ? {
|
|
662
663
|
alignSelf: "center",
|
|
663
664
|
outlineStyle: "none",
|
|
@@ -669,6 +670,18 @@ var inputFieldMetrics = reactNative.StyleSheet.create({
|
|
|
669
670
|
/** Single-line: avoid Android lineHeight jump between placeholder and typed text. */
|
|
670
671
|
inputSingleLine: {
|
|
671
672
|
...reactNative.Platform.OS === "android" ? { textAlignVertical: "center" } : null
|
|
673
|
+
},
|
|
674
|
+
/**
|
|
675
|
+
* Multiline fields should not flex-fill the container — on iOS a tall TextInput
|
|
676
|
+
* vertically centers the placeholder.
|
|
677
|
+
*/
|
|
678
|
+
inputMultiline: {
|
|
679
|
+
flexGrow: 0,
|
|
680
|
+
flexShrink: 1,
|
|
681
|
+
flexBasis: "auto",
|
|
682
|
+
width: "100%",
|
|
683
|
+
alignSelf: "stretch",
|
|
684
|
+
textAlignVertical: "top"
|
|
672
685
|
}
|
|
673
686
|
});
|
|
674
687
|
function Label({
|
|
@@ -717,6 +730,25 @@ function renderInputIcon(icon, color) {
|
|
|
717
730
|
}
|
|
718
731
|
return icon;
|
|
719
732
|
}
|
|
733
|
+
var INTEGER_KEYBOARD_TYPES = /* @__PURE__ */ new Set([
|
|
734
|
+
"numeric",
|
|
735
|
+
"number-pad",
|
|
736
|
+
"phone-pad"
|
|
737
|
+
]);
|
|
738
|
+
function sanitizeNumericInput(value, keyboardType) {
|
|
739
|
+
if (keyboardType === "decimal-pad") {
|
|
740
|
+
const normalized = value.replace(/,/g, ".").replace(/[^\d.]/g, "");
|
|
741
|
+
const separatorIndex = normalized.indexOf(".");
|
|
742
|
+
if (separatorIndex === -1) {
|
|
743
|
+
return normalized;
|
|
744
|
+
}
|
|
745
|
+
return normalized.slice(0, separatorIndex + 1) + normalized.slice(separatorIndex + 1).replace(/\./g, "");
|
|
746
|
+
}
|
|
747
|
+
if (keyboardType && INTEGER_KEYBOARD_TYPES.has(keyboardType)) {
|
|
748
|
+
return value.replace(/\D/g, "");
|
|
749
|
+
}
|
|
750
|
+
return value;
|
|
751
|
+
}
|
|
720
752
|
function Input({
|
|
721
753
|
label,
|
|
722
754
|
leftIcon,
|
|
@@ -739,7 +771,10 @@ function Input({
|
|
|
739
771
|
showPasswordToggle,
|
|
740
772
|
onFocus,
|
|
741
773
|
onBlur,
|
|
774
|
+
onChangeText,
|
|
775
|
+
keyboardType,
|
|
742
776
|
multiline,
|
|
777
|
+
textAlign = "left",
|
|
743
778
|
textAlignVertical,
|
|
744
779
|
...props
|
|
745
780
|
}) {
|
|
@@ -773,6 +808,9 @@ function Input({
|
|
|
773
808
|
setFocused(false);
|
|
774
809
|
onBlur?.(event);
|
|
775
810
|
}
|
|
811
|
+
function handleChangeText(value) {
|
|
812
|
+
onChangeText?.(sanitizeNumericInput(value, keyboardType));
|
|
813
|
+
}
|
|
776
814
|
const helperMessage = error ?? hint;
|
|
777
815
|
function togglePasswordVisibility() {
|
|
778
816
|
if (!isDisabled) {
|
|
@@ -817,20 +855,22 @@ function Input({
|
|
|
817
855
|
ref: inputRef,
|
|
818
856
|
style: [
|
|
819
857
|
inputFieldMetrics.input,
|
|
820
|
-
|
|
858
|
+
multiline ? inputFieldMetrics.inputMultiline : inputFieldMetrics.inputSingleLine,
|
|
821
859
|
fieldStyles.text,
|
|
822
860
|
style
|
|
823
861
|
],
|
|
824
862
|
placeholderTextColor: fieldStyles.placeholder,
|
|
825
863
|
editable,
|
|
864
|
+
keyboardType,
|
|
826
865
|
multiline,
|
|
827
866
|
secureTextEntry: effectiveSecureTextEntry,
|
|
828
|
-
textAlign
|
|
867
|
+
textAlign,
|
|
829
868
|
textAlignVertical: resolvedTextAlignVertical,
|
|
830
869
|
onFocus: handleFocus,
|
|
831
870
|
onBlur: handleBlur,
|
|
832
871
|
accessibilityState: { disabled: isDisabled },
|
|
833
|
-
...props
|
|
872
|
+
...props,
|
|
873
|
+
onChangeText: handleChangeText
|
|
834
874
|
}
|
|
835
875
|
),
|
|
836
876
|
trailingIcon ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles3.iconSlot, children: trailingIcon }) : null
|
|
@@ -1386,13 +1426,6 @@ function Select({
|
|
|
1386
1426
|
inputRange: [0, 1],
|
|
1387
1427
|
outputRange: ["0deg", "180deg"]
|
|
1388
1428
|
});
|
|
1389
|
-
const hasError = Boolean(error) || Boolean(invalid);
|
|
1390
|
-
const visualState = resolveInputVisualState({
|
|
1391
|
-
focused: open,
|
|
1392
|
-
error: hasError,
|
|
1393
|
-
disabled
|
|
1394
|
-
});
|
|
1395
|
-
const fieldStyles = getSelectFieldStyles(visualState);
|
|
1396
1429
|
const selectedValues = react.useMemo(
|
|
1397
1430
|
() => normalizeSelectedValues(multiple, value),
|
|
1398
1431
|
[multiple, value]
|
|
@@ -1406,6 +1439,14 @@ function Select({
|
|
|
1406
1439
|
() => options.filter((option) => !option.disabled),
|
|
1407
1440
|
[options]
|
|
1408
1441
|
);
|
|
1442
|
+
const isEffectivelyDisabled = disabled || selectableOptions.length === 0;
|
|
1443
|
+
const hasError = Boolean(error) || Boolean(invalid);
|
|
1444
|
+
const visualState = resolveInputVisualState({
|
|
1445
|
+
focused: open,
|
|
1446
|
+
error: hasError,
|
|
1447
|
+
disabled: isEffectivelyDisabled
|
|
1448
|
+
});
|
|
1449
|
+
const fieldStyles = getSelectFieldStyles(visualState);
|
|
1409
1450
|
const selectableIndexByValue = react.useMemo(
|
|
1410
1451
|
() => new Map(
|
|
1411
1452
|
selectableOptions.map((option, index) => [option.value, index])
|
|
@@ -1433,7 +1474,7 @@ function Select({
|
|
|
1433
1474
|
setHighlightedIndex(-1);
|
|
1434
1475
|
}
|
|
1435
1476
|
function openMenu() {
|
|
1436
|
-
if (
|
|
1477
|
+
if (isEffectivelyDisabled) {
|
|
1437
1478
|
return;
|
|
1438
1479
|
}
|
|
1439
1480
|
triggerRef.current?.measureInWindow((x, y, width, height) => {
|
|
@@ -1452,7 +1493,6 @@ function Select({
|
|
|
1452
1493
|
return;
|
|
1453
1494
|
}
|
|
1454
1495
|
if (selectedValues.includes(nextValue)) {
|
|
1455
|
-
onValueChange?.("");
|
|
1456
1496
|
closeMenu();
|
|
1457
1497
|
return;
|
|
1458
1498
|
}
|
|
@@ -1482,14 +1522,14 @@ function Select({
|
|
|
1482
1522
|
});
|
|
1483
1523
|
const dropdownTop = anchor ? resolveSelectDropdownTop(anchor, dropdownHeight) : 0;
|
|
1484
1524
|
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { ref: wrapperRef, style: [styles4.wrapper, containerStyle], children: [
|
|
1485
|
-
label ? /* @__PURE__ */ jsxRuntime.jsx(Label, { disabled, style: styles4.label, className: labelClassName, children: label }) : null,
|
|
1525
|
+
label ? /* @__PURE__ */ jsxRuntime.jsx(Label, { disabled: isEffectivelyDisabled, style: styles4.label, className: labelClassName, children: label }) : null,
|
|
1486
1526
|
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: fieldStyles.outline, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1487
1527
|
reactNative.Pressable,
|
|
1488
1528
|
{
|
|
1489
1529
|
ref: triggerRef,
|
|
1490
1530
|
accessibilityRole: "button",
|
|
1491
|
-
accessibilityState: { disabled, expanded: open },
|
|
1492
|
-
disabled,
|
|
1531
|
+
accessibilityState: { disabled: isEffectivelyDisabled, expanded: open },
|
|
1532
|
+
disabled: isEffectivelyDisabled,
|
|
1493
1533
|
onPress: open ? closeMenu : openMenu,
|
|
1494
1534
|
style: [selectFieldMetrics.container, fieldStyles.container, fieldStyle],
|
|
1495
1535
|
children: [
|
|
@@ -1523,7 +1563,7 @@ function Select({
|
|
|
1523
1563
|
ChevronDownIcon,
|
|
1524
1564
|
{
|
|
1525
1565
|
size: SELECT_CHEVRON_SIZE,
|
|
1526
|
-
color:
|
|
1566
|
+
color: isEffectivelyDisabled ? colors.stormGray200 : SELECT_CHEVRON_COLOR
|
|
1527
1567
|
}
|
|
1528
1568
|
)
|
|
1529
1569
|
}
|
|
@@ -1532,35 +1572,46 @@ function Select({
|
|
|
1532
1572
|
}
|
|
1533
1573
|
) }),
|
|
1534
1574
|
helperMessage ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { ref: helperRef, style: error ? styles4.error : styles4.hint, children: helperMessage }) : null,
|
|
1535
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Modal, { visible: open, transparent: true, animationType: "fade", onRequestClose: closeMenu, children: /* @__PURE__ */ jsxRuntime.
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1575
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Modal, { visible: open, transparent: true, animationType: "fade", onRequestClose: closeMenu, children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles4.overlay, children: [
|
|
1576
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1577
|
+
reactNative.Pressable,
|
|
1578
|
+
{
|
|
1579
|
+
style: styles4.backdrop,
|
|
1580
|
+
onPress: closeMenu,
|
|
1581
|
+
accessibilityRole: "button",
|
|
1582
|
+
accessibilityLabel: "Close"
|
|
1583
|
+
}
|
|
1584
|
+
),
|
|
1585
|
+
anchor ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1586
|
+
reactNative.View,
|
|
1587
|
+
{
|
|
1588
|
+
ref: menuRef,
|
|
1589
|
+
style: [
|
|
1590
|
+
selectDropdownMetrics.menu,
|
|
1591
|
+
styles4.dropdown,
|
|
1592
|
+
{
|
|
1593
|
+
top: dropdownTop,
|
|
1594
|
+
left: anchor.x,
|
|
1595
|
+
width: anchor.width,
|
|
1596
|
+
height: dropdownHeight
|
|
1597
|
+
}
|
|
1598
|
+
],
|
|
1599
|
+
children: needsScroll ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1600
|
+
reactNative.ScrollView,
|
|
1601
|
+
{
|
|
1602
|
+
ref: scrollRef,
|
|
1603
|
+
style: styles4.dropdownScroll,
|
|
1604
|
+
contentContainerStyle: styles4.dropdownContent,
|
|
1605
|
+
keyboardShouldPersistTaps: "handled",
|
|
1606
|
+
showsVerticalScrollIndicator: true,
|
|
1607
|
+
bounces: false,
|
|
1608
|
+
nestedScrollEnabled: true,
|
|
1609
|
+
children: optionList
|
|
1610
|
+
}
|
|
1611
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles4.dropdownContent, children: optionList })
|
|
1612
|
+
}
|
|
1613
|
+
) : null
|
|
1614
|
+
] }) })
|
|
1564
1615
|
] });
|
|
1565
1616
|
}
|
|
1566
1617
|
var styles4 = reactNative.StyleSheet.create({
|
|
@@ -1584,11 +1635,15 @@ var styles4 = reactNative.StyleSheet.create({
|
|
|
1584
1635
|
justifyContent: "center"
|
|
1585
1636
|
},
|
|
1586
1637
|
overlay: {
|
|
1587
|
-
flex: 1
|
|
1638
|
+
flex: 1
|
|
1639
|
+
},
|
|
1640
|
+
backdrop: {
|
|
1641
|
+
...reactNative.StyleSheet.absoluteFillObject,
|
|
1588
1642
|
backgroundColor: colors.transparent
|
|
1589
1643
|
},
|
|
1590
1644
|
dropdown: {
|
|
1591
|
-
position: "absolute"
|
|
1645
|
+
position: "absolute",
|
|
1646
|
+
zIndex: 1
|
|
1592
1647
|
},
|
|
1593
1648
|
dropdownScroll: {
|
|
1594
1649
|
flex: 1
|
|
@@ -1949,6 +2004,9 @@ var styles5 = reactNative.StyleSheet.create({
|
|
|
1949
2004
|
color: colors.slateBlue
|
|
1950
2005
|
}
|
|
1951
2006
|
});
|
|
2007
|
+
function sanitizePhoneDigits(value) {
|
|
2008
|
+
return value.replace(/\D/g, "");
|
|
2009
|
+
}
|
|
1952
2010
|
function PhoneInput({
|
|
1953
2011
|
label,
|
|
1954
2012
|
countryCode,
|
|
@@ -1966,6 +2024,7 @@ function PhoneInput({
|
|
|
1966
2024
|
editable = true,
|
|
1967
2025
|
onFocus,
|
|
1968
2026
|
onBlur,
|
|
2027
|
+
onChangeText,
|
|
1969
2028
|
...props
|
|
1970
2029
|
}) {
|
|
1971
2030
|
const wrapperRef = react.useRef(null);
|
|
@@ -1990,6 +2049,9 @@ function PhoneInput({
|
|
|
1990
2049
|
setFocused(false);
|
|
1991
2050
|
onBlur?.(event);
|
|
1992
2051
|
}
|
|
2052
|
+
function handleChangeText(value) {
|
|
2053
|
+
onChangeText?.(sanitizePhoneDigits(value));
|
|
2054
|
+
}
|
|
1993
2055
|
const helperMessage = error ?? hint;
|
|
1994
2056
|
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { ref: wrapperRef, style: [styles6.wrapper, containerStyle], children: [
|
|
1995
2057
|
label ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2034,7 +2096,8 @@ function PhoneInput({
|
|
|
2034
2096
|
onFocus: handleFocus,
|
|
2035
2097
|
onBlur: handleBlur,
|
|
2036
2098
|
accessibilityState: { disabled: isDisabled },
|
|
2037
|
-
...props
|
|
2099
|
+
...props,
|
|
2100
|
+
onChangeText: handleChangeText
|
|
2038
2101
|
}
|
|
2039
2102
|
)
|
|
2040
2103
|
}
|