@ecohouse/ui 0.1.53 → 0.1.54
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/index.cjs +116 -87
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +116 -87
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Select/Select.tsx +163 -105
package/dist/index.js
CHANGED
|
@@ -27555,7 +27555,7 @@ var require_react_dom_development = __commonJS({
|
|
|
27555
27555
|
return root2;
|
|
27556
27556
|
}
|
|
27557
27557
|
var ReactVersion = "18.3.1";
|
|
27558
|
-
function
|
|
27558
|
+
function createPortal4(children, containerInfo, implementation) {
|
|
27559
27559
|
var key = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : null;
|
|
27560
27560
|
{
|
|
27561
27561
|
checkKeyStringCoercion(key);
|
|
@@ -28411,7 +28411,7 @@ var require_react_dom_development = __commonJS({
|
|
|
28411
28411
|
if (!isValidContainer(container)) {
|
|
28412
28412
|
throw new Error("Target container is not a DOM element.");
|
|
28413
28413
|
}
|
|
28414
|
-
return
|
|
28414
|
+
return createPortal4(children, container, null, key);
|
|
28415
28415
|
}
|
|
28416
28416
|
function renderSubtreeIntoContainer(parentComponent, element, containerNode, callback) {
|
|
28417
28417
|
return unstable_renderSubtreeIntoContainer(parentComponent, element, containerNode, callback);
|
|
@@ -36208,6 +36208,9 @@ var styles32 = StyleSheet.create({
|
|
|
36208
36208
|
color: colors.red
|
|
36209
36209
|
}
|
|
36210
36210
|
});
|
|
36211
|
+
|
|
36212
|
+
// src/components/Select/Select.tsx
|
|
36213
|
+
var import_react_dom3 = __toESM(require_react_dom());
|
|
36211
36214
|
var DEFAULT_WIDTH4 = 308;
|
|
36212
36215
|
var TRIGGER_HEIGHT2 = 44;
|
|
36213
36216
|
var TRIGGER_RADIUS2 = 60;
|
|
@@ -36217,6 +36220,9 @@ var ITEM_RADIUS2 = 12;
|
|
|
36217
36220
|
var ICON_SIZE13 = 20;
|
|
36218
36221
|
var CHIP_GAP = 6;
|
|
36219
36222
|
var FALLBACK_ELLIPSIS_WIDTH = 20;
|
|
36223
|
+
var WEB_MENU_Z_INDEX = 600;
|
|
36224
|
+
var WEB_VIEWPORT_PADDING = 8;
|
|
36225
|
+
var WEB_MENU_GAP = 8;
|
|
36220
36226
|
function itemBackground(state) {
|
|
36221
36227
|
switch (state) {
|
|
36222
36228
|
case "hover":
|
|
@@ -36363,6 +36369,7 @@ var Select = forwardRef(
|
|
|
36363
36369
|
const valueProp = props.value;
|
|
36364
36370
|
const rootRef = useRef(null);
|
|
36365
36371
|
const triggerRef = useRef(null);
|
|
36372
|
+
const menuRef = useRef(null);
|
|
36366
36373
|
const searchInputRef = useRef(null);
|
|
36367
36374
|
const setRootRef = useMemo(() => mergeRefs(rootRef, forwardedRef), [forwardedRef]);
|
|
36368
36375
|
const isOpenControlled = typeof openProp === "boolean";
|
|
@@ -36378,6 +36385,7 @@ var Select = forwardRef(
|
|
|
36378
36385
|
const [hoveredValue, setHoveredValue] = useState(null);
|
|
36379
36386
|
const [menuAlignEnd, setMenuAlignEnd] = useState(false);
|
|
36380
36387
|
const [menuPlaceAbove, setMenuPlaceAbove] = useState(false);
|
|
36388
|
+
const [webMenuPosition, setWebMenuPosition] = useState(null);
|
|
36381
36389
|
const selectedValues = useMemo(() => {
|
|
36382
36390
|
const current = isValueControlled ? valueProp : multiple ? uncontrolledMultiple : uncontrolledSingle;
|
|
36383
36391
|
return toArray(current);
|
|
@@ -36431,6 +36439,7 @@ var Select = forwardRef(
|
|
|
36431
36439
|
setHoveredValue(null);
|
|
36432
36440
|
setMenuAlignEnd(false);
|
|
36433
36441
|
setMenuPlaceAbove(false);
|
|
36442
|
+
setWebMenuPosition(null);
|
|
36434
36443
|
onSearchChange?.("");
|
|
36435
36444
|
}
|
|
36436
36445
|
},
|
|
@@ -36442,15 +36451,18 @@ var Select = forwardRef(
|
|
|
36442
36451
|
const trigger = triggerRef.current;
|
|
36443
36452
|
const rect = trigger?.getBoundingClientRect?.();
|
|
36444
36453
|
if (!rect) return;
|
|
36445
|
-
const viewportPadding = 8;
|
|
36446
|
-
const gap = 8;
|
|
36447
36454
|
const menuWidth = Math.max(rect.width, resolvedMenuWidth ?? 0);
|
|
36448
|
-
const overflowsRight = rect.left + menuWidth > window.innerWidth -
|
|
36455
|
+
const overflowsRight = rect.left + menuWidth > window.innerWidth - WEB_VIEWPORT_PADDING;
|
|
36449
36456
|
setMenuAlignEnd(overflowsRight);
|
|
36450
|
-
const spaceBelow = window.innerHeight -
|
|
36451
|
-
const spaceAbove = rect.top -
|
|
36452
|
-
const needsAbove = estimatedMenuHeight +
|
|
36457
|
+
const spaceBelow = window.innerHeight - WEB_VIEWPORT_PADDING - rect.bottom;
|
|
36458
|
+
const spaceAbove = rect.top - WEB_VIEWPORT_PADDING;
|
|
36459
|
+
const needsAbove = estimatedMenuHeight + WEB_MENU_GAP > spaceBelow && spaceAbove > spaceBelow;
|
|
36453
36460
|
setMenuPlaceAbove(needsAbove);
|
|
36461
|
+
const available = Math.max(0, (needsAbove ? spaceAbove : spaceBelow) - WEB_MENU_GAP);
|
|
36462
|
+
const maxHeight = Math.min(estimatedMenuHeight, Math.max(available, TRIGGER_HEIGHT2));
|
|
36463
|
+
const left = overflowsRight ? Math.max(WEB_VIEWPORT_PADDING, rect.right - menuWidth) : Math.min(rect.left, window.innerWidth - WEB_VIEWPORT_PADDING - menuWidth);
|
|
36464
|
+
const top = needsAbove ? Math.max(WEB_VIEWPORT_PADDING, rect.top - WEB_MENU_GAP - maxHeight) : rect.bottom + WEB_MENU_GAP;
|
|
36465
|
+
setWebMenuPosition({ top, left, width: menuWidth, maxHeight });
|
|
36454
36466
|
};
|
|
36455
36467
|
updateMenuPlacement();
|
|
36456
36468
|
window.addEventListener("resize", updateMenuPlacement);
|
|
@@ -36467,11 +36479,12 @@ var Select = forwardRef(
|
|
|
36467
36479
|
useEffect(() => {
|
|
36468
36480
|
if (Platform.OS !== "web" || !isOpen) return;
|
|
36469
36481
|
const handlePointerDown = (event) => {
|
|
36470
|
-
const root = rootRef.current;
|
|
36471
36482
|
const target = event.target;
|
|
36472
|
-
if (
|
|
36473
|
-
|
|
36474
|
-
|
|
36483
|
+
if (!(target instanceof Node)) return;
|
|
36484
|
+
const root = rootRef.current;
|
|
36485
|
+
const menu = menuRef.current;
|
|
36486
|
+
if (root?.contains?.(target) || menu?.contains?.(target)) return;
|
|
36487
|
+
setOpen(false);
|
|
36475
36488
|
};
|
|
36476
36489
|
document.addEventListener("mousedown", handlePointerDown);
|
|
36477
36490
|
document.addEventListener("touchstart", handlePointerDown);
|
|
@@ -36585,7 +36598,7 @@ var Select = forwardRef(
|
|
|
36585
36598
|
]);
|
|
36586
36599
|
const leftIconNode = renderStatefulIcon(leftIcon, UserIcon, {
|
|
36587
36600
|
size: ICON_SIZE13,
|
|
36588
|
-
color: error ? colors.red : colors.primary
|
|
36601
|
+
color: error ? colors.red : isOpen ? colors.primary : colors.grey100
|
|
36589
36602
|
});
|
|
36590
36603
|
const hasLeftIcon = showLeftIcon || leftIcon != null;
|
|
36591
36604
|
const triggerBorderColor = error ? colors.redMuted : isOpen ? colors.primaryMuted : colors.grey700;
|
|
@@ -36594,6 +36607,95 @@ var Select = forwardRef(
|
|
|
36594
36607
|
const hintColor = error ? colors.red : colors.grey100;
|
|
36595
36608
|
const singleLabel = selectedOptions[0]?.label ?? placeholder;
|
|
36596
36609
|
const resolvedAccessibilityLabel = accessibilityLabel ?? (typeof label === "string" ? label : void 0);
|
|
36610
|
+
const optionListMaxHeight = Platform.OS === "web" && webMenuPosition != null ? Math.max(43, webMenuPosition.maxHeight - (24 + (showSearch ? 48 : 0))) : resolvedOptionListMaxHeight;
|
|
36611
|
+
const menuNode = isOpen ? /* @__PURE__ */ jsxs(
|
|
36612
|
+
View,
|
|
36613
|
+
{
|
|
36614
|
+
ref: menuRef,
|
|
36615
|
+
style: [
|
|
36616
|
+
styles33.menu,
|
|
36617
|
+
Platform.OS === "web" && webMenuPosition != null ? {
|
|
36618
|
+
position: "fixed",
|
|
36619
|
+
top: webMenuPosition.top,
|
|
36620
|
+
left: webMenuPosition.left,
|
|
36621
|
+
width: webMenuPosition.width,
|
|
36622
|
+
minWidth: webMenuPosition.width,
|
|
36623
|
+
maxHeight: webMenuPosition.maxHeight,
|
|
36624
|
+
zIndex: WEB_MENU_Z_INDEX,
|
|
36625
|
+
marginTop: 0,
|
|
36626
|
+
marginBottom: 0
|
|
36627
|
+
} : Platform.OS === "web" ? { position: "fixed", opacity: 0, pointerEvents: "none" } : [
|
|
36628
|
+
menuAlignEnd ? styles33.menuAlignEnd : styles33.menuAlignStart,
|
|
36629
|
+
menuPlaceAbove ? styles33.menuAbove : styles33.menuBelow
|
|
36630
|
+
],
|
|
36631
|
+
menuStyle
|
|
36632
|
+
],
|
|
36633
|
+
children: [
|
|
36634
|
+
showSearch ? /* @__PURE__ */ jsxs(View, { style: styles33.searchField, children: [
|
|
36635
|
+
/* @__PURE__ */ jsx(View, { style: styles33.iconSlot, children: /* @__PURE__ */ jsx(SearchIcon, { size: ICON_SIZE13, color: colors.grey100 }) }),
|
|
36636
|
+
/* @__PURE__ */ jsx(
|
|
36637
|
+
TextInput,
|
|
36638
|
+
{
|
|
36639
|
+
ref: searchInputRef,
|
|
36640
|
+
value: searchQuery,
|
|
36641
|
+
onChangeText: handleSearchChange,
|
|
36642
|
+
editable: !disabled,
|
|
36643
|
+
placeholder: searchPlaceholder,
|
|
36644
|
+
placeholderTextColor: colors.grey100,
|
|
36645
|
+
style: [
|
|
36646
|
+
styles33.searchInput,
|
|
36647
|
+
Platform.OS === "web" ? styles33.searchInputWeb : null,
|
|
36648
|
+
Platform.OS === "android" ? styles33.searchInputAndroid : null
|
|
36649
|
+
],
|
|
36650
|
+
accessibilityLabel: searchPlaceholder
|
|
36651
|
+
}
|
|
36652
|
+
)
|
|
36653
|
+
] }) : null,
|
|
36654
|
+
/* @__PURE__ */ jsxs(
|
|
36655
|
+
ScrollView,
|
|
36656
|
+
{
|
|
36657
|
+
style: [styles33.optionList, { maxHeight: optionListMaxHeight }],
|
|
36658
|
+
contentContainerStyle: styles33.optionListContent,
|
|
36659
|
+
keyboardShouldPersistTaps: "handled",
|
|
36660
|
+
showsVerticalScrollIndicator: false,
|
|
36661
|
+
children: [
|
|
36662
|
+
loading ? /* @__PURE__ */ jsx(View, { style: styles33.statusRow, children: /* @__PURE__ */ jsx(Text, { style: styles33.statusText, children: "Loading..." }) }) : filteredOptions.length === 0 ? /* @__PURE__ */ jsx(View, { style: styles33.statusRow, children: /* @__PURE__ */ jsx(Text, { style: styles33.statusText, children: emptyText }) }) : null,
|
|
36663
|
+
!loading && filteredOptions.map((option) => {
|
|
36664
|
+
const isSelected = selectedValues.includes(option.value);
|
|
36665
|
+
const isHovered = hoveredValue === option.value;
|
|
36666
|
+
const visualState = isSelected ? "selected" : isHovered ? "hover" : "default";
|
|
36667
|
+
return /* @__PURE__ */ jsxs(
|
|
36668
|
+
Pressable,
|
|
36669
|
+
{
|
|
36670
|
+
onPress: () => handleSelect(option.value),
|
|
36671
|
+
disabled,
|
|
36672
|
+
onHoverIn: () => setHoveredValue(option.value),
|
|
36673
|
+
onHoverOut: () => setHoveredValue((current) => current === option.value ? null : current),
|
|
36674
|
+
onPressIn: () => setHoveredValue(option.value),
|
|
36675
|
+
onPressOut: () => setHoveredValue((current) => current === option.value ? null : current),
|
|
36676
|
+
accessibilityRole: multiple ? "checkbox" : "button",
|
|
36677
|
+
accessibilityState: { selected: isSelected, checked: isSelected, disabled },
|
|
36678
|
+
style: [
|
|
36679
|
+
styles33.item,
|
|
36680
|
+
{
|
|
36681
|
+
backgroundColor: itemBackground(visualState)
|
|
36682
|
+
}
|
|
36683
|
+
],
|
|
36684
|
+
children: [
|
|
36685
|
+
multiple ? /* @__PURE__ */ jsx(View, { style: [styles33.itemCheckbox, { pointerEvents: "none" }], children: /* @__PURE__ */ jsx(Checkbox, { value: isSelected, variant: "light" }) }) : null,
|
|
36686
|
+
/* @__PURE__ */ jsx(Text, { style: styles33.itemLabel, numberOfLines: 1, children: option.label })
|
|
36687
|
+
]
|
|
36688
|
+
},
|
|
36689
|
+
option.value
|
|
36690
|
+
);
|
|
36691
|
+
})
|
|
36692
|
+
]
|
|
36693
|
+
}
|
|
36694
|
+
)
|
|
36695
|
+
]
|
|
36696
|
+
}
|
|
36697
|
+
) : null;
|
|
36698
|
+
const webMenuPortal = Platform.OS === "web" && isOpen && typeof document !== "undefined" ? (0, import_react_dom3.createPortal)(menuNode, document.body) : null;
|
|
36597
36699
|
return /* @__PURE__ */ jsxs(
|
|
36598
36700
|
View,
|
|
36599
36701
|
{
|
|
@@ -36634,80 +36736,7 @@ var Select = forwardRef(
|
|
|
36634
36736
|
]
|
|
36635
36737
|
}
|
|
36636
36738
|
),
|
|
36637
|
-
|
|
36638
|
-
View,
|
|
36639
|
-
{
|
|
36640
|
-
style: [
|
|
36641
|
-
styles33.menu,
|
|
36642
|
-
menuAlignEnd ? styles33.menuAlignEnd : styles33.menuAlignStart,
|
|
36643
|
-
menuPlaceAbove ? styles33.menuAbove : styles33.menuBelow,
|
|
36644
|
-
menuStyle
|
|
36645
|
-
],
|
|
36646
|
-
children: [
|
|
36647
|
-
showSearch ? /* @__PURE__ */ jsxs(View, { style: styles33.searchField, children: [
|
|
36648
|
-
/* @__PURE__ */ jsx(View, { style: styles33.iconSlot, children: /* @__PURE__ */ jsx(SearchIcon, { size: ICON_SIZE13, color: colors.grey100 }) }),
|
|
36649
|
-
/* @__PURE__ */ jsx(
|
|
36650
|
-
TextInput,
|
|
36651
|
-
{
|
|
36652
|
-
ref: searchInputRef,
|
|
36653
|
-
value: searchQuery,
|
|
36654
|
-
onChangeText: handleSearchChange,
|
|
36655
|
-
editable: !disabled,
|
|
36656
|
-
placeholder: searchPlaceholder,
|
|
36657
|
-
placeholderTextColor: colors.grey100,
|
|
36658
|
-
style: [
|
|
36659
|
-
styles33.searchInput,
|
|
36660
|
-
Platform.OS === "web" ? styles33.searchInputWeb : null,
|
|
36661
|
-
Platform.OS === "android" ? styles33.searchInputAndroid : null
|
|
36662
|
-
],
|
|
36663
|
-
accessibilityLabel: searchPlaceholder
|
|
36664
|
-
}
|
|
36665
|
-
)
|
|
36666
|
-
] }) : null,
|
|
36667
|
-
/* @__PURE__ */ jsxs(
|
|
36668
|
-
ScrollView,
|
|
36669
|
-
{
|
|
36670
|
-
style: [styles33.optionList, { maxHeight: resolvedOptionListMaxHeight }],
|
|
36671
|
-
contentContainerStyle: styles33.optionListContent,
|
|
36672
|
-
keyboardShouldPersistTaps: "handled",
|
|
36673
|
-
showsVerticalScrollIndicator: false,
|
|
36674
|
-
children: [
|
|
36675
|
-
loading ? /* @__PURE__ */ jsx(View, { style: styles33.statusRow, children: /* @__PURE__ */ jsx(Text, { style: styles33.statusText, children: "Loading..." }) }) : filteredOptions.length === 0 ? /* @__PURE__ */ jsx(View, { style: styles33.statusRow, children: /* @__PURE__ */ jsx(Text, { style: styles33.statusText, children: emptyText }) }) : null,
|
|
36676
|
-
!loading && filteredOptions.map((option) => {
|
|
36677
|
-
const isSelected = selectedValues.includes(option.value);
|
|
36678
|
-
const isHovered = hoveredValue === option.value;
|
|
36679
|
-
const visualState = isSelected ? "selected" : isHovered ? "hover" : "default";
|
|
36680
|
-
return /* @__PURE__ */ jsxs(
|
|
36681
|
-
Pressable,
|
|
36682
|
-
{
|
|
36683
|
-
onPress: () => handleSelect(option.value),
|
|
36684
|
-
disabled,
|
|
36685
|
-
onHoverIn: () => setHoveredValue(option.value),
|
|
36686
|
-
onHoverOut: () => setHoveredValue((current) => current === option.value ? null : current),
|
|
36687
|
-
onPressIn: () => setHoveredValue(option.value),
|
|
36688
|
-
onPressOut: () => setHoveredValue((current) => current === option.value ? null : current),
|
|
36689
|
-
accessibilityRole: multiple ? "checkbox" : "button",
|
|
36690
|
-
accessibilityState: { selected: isSelected, checked: isSelected, disabled },
|
|
36691
|
-
style: [
|
|
36692
|
-
styles33.item,
|
|
36693
|
-
{
|
|
36694
|
-
backgroundColor: itemBackground(visualState)
|
|
36695
|
-
}
|
|
36696
|
-
],
|
|
36697
|
-
children: [
|
|
36698
|
-
multiple ? /* @__PURE__ */ jsx(View, { style: [styles33.itemCheckbox, { pointerEvents: "none" }], children: /* @__PURE__ */ jsx(Checkbox, { value: isSelected, variant: "light" }) }) : null,
|
|
36699
|
-
/* @__PURE__ */ jsx(Text, { style: styles33.itemLabel, numberOfLines: 1, children: option.label })
|
|
36700
|
-
]
|
|
36701
|
-
},
|
|
36702
|
-
option.value
|
|
36703
|
-
);
|
|
36704
|
-
})
|
|
36705
|
-
]
|
|
36706
|
-
}
|
|
36707
|
-
)
|
|
36708
|
-
]
|
|
36709
|
-
}
|
|
36710
|
-
) : null
|
|
36739
|
+
Platform.OS === "web" ? webMenuPortal : menuNode
|
|
36711
36740
|
] }),
|
|
36712
36741
|
showHint && hint ? /* @__PURE__ */ jsx(Text, { style: [styles33.hint, { color: hintColor }], children: hint }) : null
|
|
36713
36742
|
]
|