@scripso-homepad/ui 0.4.13 → 0.4.15

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.
@@ -28766,22 +28766,28 @@ var inputFieldMetrics = reactNative.StyleSheet.create({
28766
28766
  input: {
28767
28767
  flex: 1,
28768
28768
  minWidth: 0,
28769
+ width: "100%",
28769
28770
  fontFamily: fonts.sans,
28770
28771
  fontSize: fontSize.md,
28771
28772
  fontWeight: fontWeight.medium,
28772
- lineHeight: INPUT_TEXT_LINE_HEIGHT,
28773
28773
  paddingVertical: 0,
28774
28774
  paddingHorizontal: 0,
28775
28775
  margin: 0,
28776
28776
  borderWidth: 0,
28777
28777
  backgroundColor: colors.transparent,
28778
28778
  ...reactNative.Platform.OS === "android" ? { includeFontPadding: false } : null,
28779
+ ...reactNative.Platform.OS === "ios" ? { lineHeight: INPUT_TEXT_LINE_HEIGHT, paddingVertical: 2 } : null,
28779
28780
  ...reactNative.Platform.OS === "web" ? {
28780
28781
  alignSelf: "center",
28781
- outlineStyle: "none"
28782
+ outlineStyle: "none",
28783
+ lineHeight: INPUT_TEXT_LINE_HEIGHT
28782
28784
  } : {
28783
28785
  alignSelf: "stretch"
28784
28786
  }
28787
+ },
28788
+ /** Single-line: avoid Android lineHeight jump between placeholder and typed text. */
28789
+ inputSingleLine: {
28790
+ ...reactNative.Platform.OS === "android" ? { textAlignVertical: "center" } : null
28785
28791
  }
28786
28792
  });
28787
28793
  function hasClassList(node) {
@@ -28870,6 +28876,7 @@ function Input({
28870
28876
  fieldClassName,
28871
28877
  fieldStyle,
28872
28878
  labelClassName,
28879
+ labelStyles,
28873
28880
  inputClassName,
28874
28881
  errorClassName,
28875
28882
  hintClassName,
@@ -28878,6 +28885,8 @@ function Input({
28878
28885
  showPasswordToggle,
28879
28886
  onFocus,
28880
28887
  onBlur,
28888
+ multiline,
28889
+ textAlignVertical,
28881
28890
  ...props
28882
28891
  }) {
28883
28892
  const wrapperRef = react.useRef(null);
@@ -28894,6 +28903,7 @@ function Input({
28894
28903
  const hasError = Boolean(error) || Boolean(invalid);
28895
28904
  const passwordToggleEnabled = secureTextEntry === true && showPasswordToggle !== false && rightIcon == null;
28896
28905
  const effectiveSecureTextEntry = passwordToggleEnabled ? !passwordVisible : secureTextEntry;
28906
+ const resolvedTextAlignVertical = textAlignVertical ?? (multiline ? "top" : "center");
28897
28907
  const visualState = resolveInputVisualState({
28898
28908
  focused,
28899
28909
  error: hasError,
@@ -28931,7 +28941,15 @@ function Input({
28931
28941
  }
28932
28942
  ) : rightIcon ? renderInputIcon(rightIcon, iconColor) : null;
28933
28943
  return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { ref: wrapperRef, style: [styles2.wrapper, containerStyle], children: [
28934
- label ? /* @__PURE__ */ jsxRuntime.jsx(Label, { disabled: isDisabled, className: labelClassName, children: label }) : null,
28944
+ label ? /* @__PURE__ */ jsxRuntime.jsx(
28945
+ Label,
28946
+ {
28947
+ disabled: isDisabled,
28948
+ className: labelClassName,
28949
+ style: labelStyles,
28950
+ children: label
28951
+ }
28952
+ ) : null,
28935
28953
  /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: fieldStyles.outline, children: /* @__PURE__ */ jsxRuntime.jsxs(
28936
28954
  reactNative.View,
28937
28955
  {
@@ -28945,12 +28963,16 @@ function Input({
28945
28963
  ref: inputRef,
28946
28964
  style: [
28947
28965
  inputFieldMetrics.input,
28966
+ !multiline ? inputFieldMetrics.inputSingleLine : null,
28948
28967
  fieldStyles.text,
28949
28968
  style
28950
28969
  ],
28951
28970
  placeholderTextColor: fieldStyles.placeholder,
28952
28971
  editable,
28972
+ multiline,
28953
28973
  secureTextEntry: effectiveSecureTextEntry,
28974
+ textAlign: "left",
28975
+ textAlignVertical: resolvedTextAlignVertical,
28954
28976
  onFocus: handleFocus,
28955
28977
  onBlur: handleBlur,
28956
28978
  accessibilityState: { disabled: isDisabled },
@@ -29295,6 +29317,7 @@ function AppHeader({
29295
29317
  title,
29296
29318
  labels,
29297
29319
  hasBuildingSelect = false,
29320
+ showSearch = true,
29298
29321
  buildingOptions = [],
29299
29322
  selectedBuildingId = "",
29300
29323
  className,
@@ -29337,7 +29360,7 @@ function AppHeader({
29337
29360
  chevronIcon: buildingChevronIcon
29338
29361
  }
29339
29362
  ) : null,
29340
- /* @__PURE__ */ jsxRuntime.jsx(
29363
+ showSearch ? /* @__PURE__ */ jsxRuntime.jsx(
29341
29364
  Input,
29342
29365
  {
29343
29366
  leftIcon: searchIcon ?? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { strokeWidth: 1.75 }),
@@ -29350,7 +29373,7 @@ function AppHeader({
29350
29373
  fieldStyle: searchFieldStyle ?? defaultSearchFieldStyle,
29351
29374
  accessibilityLabel: labels.searchPlaceholder
29352
29375
  }
29353
- ),
29376
+ ) : null,
29354
29377
  /* @__PURE__ */ jsxRuntime.jsx(
29355
29378
  "button",
29356
29379
  {
@@ -30331,7 +30354,8 @@ function TableActionsCell({ className, children, ...props }) {
30331
30354
  tableCellPaddingClassName,
30332
30355
  tableBodyClassName,
30333
30356
  tableStickyRightShadowClassName,
30334
- disabled && tableRowDisabledCellClassName,
30357
+ // Keep an opaque sticky background so scrolled cells never bleed through.
30358
+ disabled && "bg-white [&>*]:opacity-70",
30335
30359
  className
30336
30360
  ),
30337
30361
  ...props,
@@ -30389,12 +30413,12 @@ var MENU_WIDTH_PX = 231;
30389
30413
  var MENU_OFFSET_PX = 4;
30390
30414
  var MENU_VIEWPORT_MARGIN_PX = 8;
30391
30415
  var useIsomorphicLayoutEffect = typeof window === "undefined" ? react.useEffect : react.useLayoutEffect;
30392
- function clampMenuLeft(left) {
30416
+ function clampMenuLeft(left, menuWidth) {
30393
30417
  if (typeof window === "undefined") {
30394
30418
  return left;
30395
30419
  }
30396
30420
  const minLeft = MENU_VIEWPORT_MARGIN_PX;
30397
- const maxLeft = Math.max(minLeft, window.innerWidth - MENU_WIDTH_PX - MENU_VIEWPORT_MARGIN_PX);
30421
+ const maxLeft = Math.max(minLeft, window.innerWidth - menuWidth - MENU_VIEWPORT_MARGIN_PX);
30398
30422
  return Math.min(Math.max(left, minLeft), maxLeft);
30399
30423
  }
30400
30424
  function resolveMenuItemIcon(item) {
@@ -30414,7 +30438,9 @@ function TableActionsMenu({
30414
30438
  items,
30415
30439
  triggerAriaLabel,
30416
30440
  className,
30417
- menuClassName
30441
+ menuClassName,
30442
+ menuWidth = MENU_WIDTH_PX,
30443
+ menuFitContent = false
30418
30444
  }) {
30419
30445
  const [open, setOpen] = react.useState(false);
30420
30446
  const [menuPosition, setMenuPosition] = react.useState(null);
@@ -30431,11 +30457,12 @@ function TableActionsMenu({
30431
30457
  return;
30432
30458
  }
30433
30459
  const rect = trigger.getBoundingClientRect();
30460
+ const resolvedMenuWidth = menuFitContent ? menuRef.current?.getBoundingClientRect().width ?? menuWidth : menuWidth;
30434
30461
  setMenuPosition({
30435
30462
  top: rect.bottom + MENU_OFFSET_PX,
30436
- left: clampMenuLeft(rect.right - MENU_WIDTH_PX)
30463
+ left: clampMenuLeft(rect.right - resolvedMenuWidth, resolvedMenuWidth)
30437
30464
  });
30438
- }, []);
30465
+ }, [menuFitContent, menuWidth]);
30439
30466
  useOnClickOutside([rootRef, menuRef], closeMenu, open);
30440
30467
  useIsomorphicLayoutEffect(() => {
30441
30468
  if (!open) {
@@ -30444,6 +30471,12 @@ function TableActionsMenu({
30444
30471
  }
30445
30472
  updateMenuPosition();
30446
30473
  }, [open, updateMenuPosition]);
30474
+ useIsomorphicLayoutEffect(() => {
30475
+ if (!open || !menuFitContent) {
30476
+ return;
30477
+ }
30478
+ updateMenuPosition();
30479
+ }, [items, menuFitContent, open, updateMenuPosition]);
30447
30480
  react.useEffect(() => {
30448
30481
  if (!open) {
30449
30482
  return;
@@ -30479,7 +30512,7 @@ function TableActionsMenu({
30479
30512
  position: "fixed",
30480
30513
  top: menuPosition.top,
30481
30514
  left: menuPosition.left,
30482
- width: MENU_WIDTH_PX
30515
+ ...menuFitContent ? { width: "max-content" } : { width: menuWidth }
30483
30516
  },
30484
30517
  className: cn(
30485
30518
  "z-50 overflow-hidden rounded-2xl border border-storm-gray-50 bg-white shadow-[0_4px_20px_0_rgba(0,0,0,0.05)]",
@@ -30501,7 +30534,8 @@ function TableActionsMenu({
30501
30534
  item.onSelect();
30502
30535
  },
30503
30536
  className: cn(
30504
- "flex h-[51px] w-full cursor-pointer items-center gap-2.5 px-3 text-left typography-14 font-medium text-storm-gray-900 transition-colors hover:bg-storm-gray-0",
30537
+ "flex h-[51px] cursor-pointer items-center gap-2.5 px-3 text-left typography-14 font-medium text-storm-gray-900 transition-colors hover:bg-storm-gray-0",
30538
+ menuFitContent ? "w-auto" : "w-full",
30505
30539
  index > 0 && "border-t border-storm-gray-50",
30506
30540
  item.disabled && "cursor-not-allowed opacity-50"
30507
30541
  ),
@@ -31065,7 +31099,10 @@ function Modal({
31065
31099
  "footer",
31066
31100
  {
31067
31101
  className: cn(
31068
- footerLayout === "split" ? "grid w-full shrink-0 grid-cols-2 gap-4" : cn("flex shrink-0 gap-4", footerAlignClasses[footerAlign])
31102
+ footerLayout === "split" ? "grid w-full shrink-0 grid-cols-1 gap-3 min-[400px]:grid-cols-2 min-[400px]:gap-4" : cn(
31103
+ "flex shrink-0 flex-col-reverse gap-3 sm:flex-row sm:gap-4",
31104
+ footerAlignClasses[footerAlign]
31105
+ )
31069
31106
  ),
31070
31107
  children: [
31071
31108
  /* @__PURE__ */ jsxRuntime.jsx(