@ecohouse/ui 0.1.24 → 0.1.26

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 CHANGED
@@ -37,6 +37,7 @@ var colors = {
37
37
  black: "#000000",
38
38
  white: "#ffffff",
39
39
  whiteAlpha86: "#FFFFFFDB",
40
+ whiteAlpha60: "#FFFFFF99",
40
41
  whiteAlpha40: "#FFFFFF66",
41
42
  whiteAlpha20: "#FFFFFF33",
42
43
  whiteAlpha6: "#FFFFFF0F",
@@ -236,6 +237,27 @@ var datePickerTypography = {
236
237
  lineHeight: 12,
237
238
  letterSpacing: 0.36
238
239
  },
240
+ rangeLabel: {
241
+ fontFamily: fonts.sans,
242
+ fontSize: 13,
243
+ fontWeight: "500",
244
+ lineHeight: 13,
245
+ letterSpacing: 0
246
+ },
247
+ rangeDate: {
248
+ fontFamily: fonts.sans,
249
+ fontSize: 16,
250
+ fontWeight: "500",
251
+ lineHeight: 16,
252
+ letterSpacing: 0
253
+ },
254
+ rangeTime: {
255
+ fontFamily: fonts.sans,
256
+ fontSize: 14,
257
+ fontWeight: "400",
258
+ lineHeight: 14,
259
+ letterSpacing: 0
260
+ },
239
261
  /** Calendar month/year heading — Bold, centered, White. */
240
262
  monthHeading: {
241
263
  fontFamily: fonts.sans,
@@ -2230,7 +2252,9 @@ var styles6 = reactNative.StyleSheet.create({
2230
2252
  var ICON_SIZE4 = 20;
2231
2253
  var ANIMATION_DURATION = 200;
2232
2254
  var OPTION_HORIZONTAL_PADDING = 16;
2255
+ var OPTION_CONTENT_GAP = 12;
2233
2256
  var OPTION_MIN_WIDTH = 97;
2257
+ var OPTION_MEASUREMENT_TOLERANCE = 0.5;
2234
2258
  var SegmentedToggle = react.forwardRef(
2235
2259
  function SegmentedToggle2({
2236
2260
  options,
@@ -2259,12 +2283,15 @@ var SegmentedToggle = react.forwardRef(
2259
2283
  const [contentWidths, setContentWidths] = react.useState([0, 0]);
2260
2284
  const [containerWidth, setContainerWidth] = react.useState(0);
2261
2285
  const availableOptionWidth = Math.max(0, (containerWidth - 12) / 2);
2262
- const widestContentWidth = Math.max(...contentWidths);
2263
- const contentBasedOptionWidth = widestContentWidth > 0 ? Math.max(OPTION_MIN_WIDTH, widestContentWidth + OPTION_HORIZONTAL_PADDING * 2) : 0;
2264
- const optionWidth = fullWidth ? availableOptionWidth : contentBasedOptionWidth;
2286
+ const resolveContentOptionWidth = (contentWidth) => contentWidth > 0 ? Math.max(
2287
+ OPTION_MIN_WIDTH,
2288
+ contentWidth + OPTION_HORIZONTAL_PADDING * 2 + OPTION_MEASUREMENT_TOLERANCE
2289
+ ) : 0;
2290
+ const optionWidths = fullWidth ? [availableOptionWidth, availableOptionWidth] : [resolveContentOptionWidth(contentWidths[0]), resolveContentOptionWidth(contentWidths[1])];
2291
+ const selectedOptionWidth = optionWidths[selectedIndex];
2265
2292
  const indicatorTranslateX = progress.interpolate({
2266
2293
  inputRange: [0, 1],
2267
- outputRange: [0, optionWidth + 4]
2294
+ outputRange: [0, optionWidths[0] + 4]
2268
2295
  });
2269
2296
  useApplyWebClassName(containerRef, resolvedClassName);
2270
2297
  react.useEffect(() => {
@@ -2302,13 +2329,37 @@ var SegmentedToggle = react.forwardRef(
2302
2329
  ],
2303
2330
  accessibilityRole: "radiogroup",
2304
2331
  children: [
2305
- optionWidth > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
2332
+ !fullWidth ? options.map(({ value: optionValue, label, icon: Icon2 }, index) => /* @__PURE__ */ jsxRuntime.jsxs(
2333
+ reactNative.View,
2334
+ {
2335
+ pointerEvents: "none",
2336
+ "aria-hidden": true,
2337
+ accessibilityElementsHidden: true,
2338
+ importantForAccessibility: "no-hide-descendants",
2339
+ onLayout: (event) => {
2340
+ const nextWidth = event.nativeEvent.layout.width;
2341
+ setContentWidths((currentWidths) => {
2342
+ if (currentWidths[index] === nextWidth) return currentWidths;
2343
+ const nextWidths = [currentWidths[0], currentWidths[1]];
2344
+ nextWidths[index] = nextWidth;
2345
+ return nextWidths;
2346
+ });
2347
+ },
2348
+ style: styles7.optionMeasurement,
2349
+ children: [
2350
+ Icon2 ? /* @__PURE__ */ jsxRuntime.jsx(Icon2, { size: ICON_SIZE4 }) : null,
2351
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles7.label, styles7.contentWidthLabel], children: label })
2352
+ ]
2353
+ },
2354
+ `${optionValue}-measurement`
2355
+ )) : null,
2356
+ selectedOptionWidth > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
2306
2357
  reactNative.Animated.View,
2307
2358
  {
2308
2359
  pointerEvents: "none",
2309
2360
  style: [
2310
2361
  styles7.activeIndicator,
2311
- { width: optionWidth, transform: [{ translateX: indicatorTranslateX }] }
2362
+ { width: selectedOptionWidth, transform: [{ translateX: indicatorTranslateX }] }
2312
2363
  ]
2313
2364
  }
2314
2365
  ) : null,
@@ -2327,27 +2378,26 @@ var SegmentedToggle = react.forwardRef(
2327
2378
  accessibilityState: { selected, disabled },
2328
2379
  style: [
2329
2380
  styles7.option,
2330
- fullWidth ? styles7.optionFullWidth : [styles7.optionContentWidth, optionWidth > 0 && { width: optionWidth }]
2381
+ fullWidth ? styles7.optionFullWidth : [
2382
+ styles7.optionContentWidth,
2383
+ optionWidths[index] > 0 && { width: optionWidths[index] }
2384
+ ]
2331
2385
  ],
2332
- children: /* @__PURE__ */ jsxRuntime.jsxs(
2333
- reactNative.View,
2334
- {
2335
- onLayout: (event) => {
2336
- const nextWidth = event.nativeEvent.layout.width;
2337
- setContentWidths((currentWidths) => {
2338
- if (currentWidths[index] === nextWidth) return currentWidths;
2339
- const nextWidths = [currentWidths[0], currentWidths[1]];
2340
- nextWidths[index] = nextWidth;
2341
- return nextWidths;
2342
- });
2343
- },
2344
- style: styles7.optionContent,
2345
- children: [
2346
- Icon2 ? /* @__PURE__ */ jsxRuntime.jsx(Icon2, { size: ICON_SIZE4, color: iconColor }) : null,
2347
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { numberOfLines: 1, style: [styles7.label, { color: labelColor }], children: label })
2348
- ]
2349
- }
2350
- )
2386
+ children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles7.optionContent, children: [
2387
+ Icon2 ? /* @__PURE__ */ jsxRuntime.jsx(Icon2, { size: ICON_SIZE4, color: iconColor }) : null,
2388
+ /* @__PURE__ */ jsxRuntime.jsx(
2389
+ reactNative.Text,
2390
+ {
2391
+ numberOfLines: fullWidth ? 1 : void 0,
2392
+ style: [
2393
+ styles7.label,
2394
+ !fullWidth && styles7.contentWidthLabel,
2395
+ { color: labelColor }
2396
+ ],
2397
+ children: label
2398
+ }
2399
+ )
2400
+ ] })
2351
2401
  },
2352
2402
  optionValue
2353
2403
  );
@@ -2389,7 +2439,14 @@ var styles7 = reactNative.StyleSheet.create({
2389
2439
  maxWidth: "100%",
2390
2440
  flexDirection: "row",
2391
2441
  alignItems: "center",
2392
- gap: 12
2442
+ gap: OPTION_CONTENT_GAP
2443
+ },
2444
+ optionMeasurement: {
2445
+ position: "absolute",
2446
+ flexDirection: "row",
2447
+ alignItems: "center",
2448
+ gap: OPTION_CONTENT_GAP,
2449
+ opacity: 0
2393
2450
  },
2394
2451
  optionFullWidth: {
2395
2452
  flex: 1,
@@ -2409,6 +2466,9 @@ var styles7 = reactNative.StyleSheet.create({
2409
2466
  label: {
2410
2467
  ...segmentedToggleTypography,
2411
2468
  flexShrink: 1
2469
+ },
2470
+ contentWidthLabel: {
2471
+ flexShrink: 0
2412
2472
  }
2413
2473
  });
2414
2474
  var defaultLanguageOptions = [
@@ -2996,6 +3056,7 @@ var DEFAULT_MONTH_NAMES = [
2996
3056
  var DEFAULT_WEEKDAY_LABELS = ["\u0535\u0550", "\u0535\u0554", "\u0549\u0550", "\u0540\u0546", "\u0548\u0552\u0550", "\u0547\u0532", "\u053F\u0550"];
2997
3057
  var EMPTY_RANGE = { start: null, end: null };
2998
3058
  var DEFAULT_WIDTH = 380;
3059
+ var RANGE_TRIGGER_WIDTH = 382;
2999
3060
  var TRIGGER_HEIGHT = 44;
3000
3061
  var TRIGGER_RADIUS = 60;
3001
3062
  var MENU_RADIUS2 = 20;
@@ -3003,10 +3064,33 @@ var ICON_SIZE7 = 20;
3003
3064
  var NAV_ICON_SIZE = 20;
3004
3065
  var DAY_CELL_HEIGHT = 44;
3005
3066
  var DAY_CIRCLE_SIZE = 44;
3067
+ function RangeTriggerField({
3068
+ label,
3069
+ value,
3070
+ time
3071
+ }) {
3072
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles12.rangeField, children: [
3073
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { numberOfLines: 1, style: styles12.rangeLabel, children: label }),
3074
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles12.rangeValueRow, children: [
3075
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { numberOfLines: 1, style: styles12.rangeDate, children: value }),
3076
+ time ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles12.rangeTimeWrap, children: [
3077
+ /* @__PURE__ */ jsxRuntime.jsx(ClockFilledIcon, { color: colors.lightGrey, size: 16 }),
3078
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles12.rangeTime, children: time })
3079
+ ] }) : null
3080
+ ] })
3081
+ ] });
3082
+ }
3006
3083
  var DatePicker = react.forwardRef(
3007
3084
  function DatePicker2(props, forwardedRef) {
3008
3085
  const {
3009
3086
  placeholder = "Select date",
3087
+ variant = "default",
3088
+ startLabel = "Start",
3089
+ endLabel = "End",
3090
+ startTime,
3091
+ endTime,
3092
+ startPlaceholder = placeholder,
3093
+ endPlaceholder = placeholder,
3010
3094
  open: openProp,
3011
3095
  defaultOpen = false,
3012
3096
  onOpenChange,
@@ -3144,18 +3228,28 @@ var DatePicker = react.forwardRef(
3144
3228
  const today = react.useMemo(() => startOfDay(/* @__PURE__ */ new Date()), []);
3145
3229
  const hasValue = isRange ? rangeValue.start != null : singleValue != null;
3146
3230
  const triggerLabel = isRange ? rangeValue.start && rangeValue.end ? `${formatValue(rangeValue.start)} - ${formatValue(rangeValue.end)}` : rangeValue.start ? `${formatValue(rangeValue.start)} - ...` : placeholder : singleValue ? formatValue(singleValue) : placeholder;
3147
- const triggerBorderColor = isOpen ? colors.primaryMuted : colors.grey700;
3231
+ const usesRangeTrigger = isRange && variant !== "default";
3232
+ const usesVerticalRangeTrigger = usesRangeTrigger && variant === "range-vertical";
3233
+ const triggerBorderColor = usesRangeTrigger ? isOpen ? colors.primary : colors.grey500 : isOpen ? colors.primaryMuted : colors.grey700;
3148
3234
  const triggerTextColor = hasValue ? colors.white : colors.grey100;
3235
+ const startValue = rangeValue.start ? formatValue(rangeValue.start) : startPlaceholder;
3236
+ const endValue = rangeValue.end ? formatValue(rangeValue.end) : endPlaceholder;
3149
3237
  const resolvedAccessibilityLabel = accessibilityLabel ?? placeholder;
3150
3238
  return /* @__PURE__ */ jsxRuntime.jsx(
3151
3239
  reactNative.View,
3152
3240
  {
3153
3241
  ...rest,
3154
3242
  ref: setRootRef,
3155
- style: [styles12.root, isOpen && styles12.rootOpen, disabled && styles12.disabled, style],
3243
+ style: [
3244
+ styles12.root,
3245
+ usesRangeTrigger && styles12.rangeRoot,
3246
+ isOpen && styles12.rootOpen,
3247
+ disabled && styles12.disabled,
3248
+ style
3249
+ ],
3156
3250
  accessibilityState: { disabled, expanded: isOpen },
3157
3251
  children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles12.triggerWrap, isOpen && styles12.triggerWrapOpen], children: [
3158
- /* @__PURE__ */ jsxRuntime.jsxs(
3252
+ /* @__PURE__ */ jsxRuntime.jsx(
3159
3253
  reactNative.Pressable,
3160
3254
  {
3161
3255
  ref: triggerRef,
@@ -3166,15 +3260,29 @@ var DatePicker = react.forwardRef(
3166
3260
  accessibilityState: { disabled, expanded: isOpen },
3167
3261
  style: [
3168
3262
  styles12.trigger,
3169
- { borderColor: triggerBorderColor, backgroundColor: colors.grey700 }
3263
+ usesRangeTrigger && styles12.rangeTrigger,
3264
+ usesRangeTrigger && (usesVerticalRangeTrigger ? styles12.rangeTriggerVertical : styles12.rangeTriggerHorizontal),
3265
+ {
3266
+ borderColor: triggerBorderColor,
3267
+ backgroundColor: usesRangeTrigger ? colors.grey800 : colors.grey700
3268
+ }
3170
3269
  ],
3171
- children: [
3270
+ children: usesRangeTrigger ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3271
+ /* @__PURE__ */ jsxRuntime.jsx(RangeTriggerField, { label: startLabel, time: startTime, value: startValue }),
3272
+ /* @__PURE__ */ jsxRuntime.jsx(
3273
+ reactNative.View,
3274
+ {
3275
+ style: usesVerticalRangeTrigger ? styles12.rangeDividerVertical : styles12.rangeDividerHorizontal
3276
+ }
3277
+ ),
3278
+ /* @__PURE__ */ jsxRuntime.jsx(RangeTriggerField, { label: endLabel, time: endTime, value: endValue })
3279
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3172
3280
  /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles12.triggerText, { color: triggerTextColor }], numberOfLines: 1, children: triggerLabel }),
3173
3281
  /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles12.iconSlot, children: /* @__PURE__ */ jsxRuntime.jsx(CalendarOutlineIcon, { size: ICON_SIZE7, color: colors.grey100 }) })
3174
- ]
3282
+ ] })
3175
3283
  }
3176
3284
  ),
3177
- isOpen ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles12.menu, calendarStyle], children: [
3285
+ isOpen ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles12.menu, usesRangeTrigger && styles12.rangeMenu, calendarStyle], children: [
3178
3286
  /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles12.calendarHeader, children: [
3179
3287
  /* @__PURE__ */ jsxRuntime.jsx(
3180
3288
  reactNative.Pressable,
@@ -3317,6 +3425,9 @@ var styles12 = reactNative.StyleSheet.create({
3317
3425
  rootOpen: {
3318
3426
  zIndex: 30
3319
3427
  },
3428
+ rangeRoot: {
3429
+ width: RANGE_TRIGGER_WIDTH
3430
+ },
3320
3431
  disabled: {
3321
3432
  opacity: 0.6
3322
3433
  },
@@ -3343,6 +3454,65 @@ var styles12 = reactNative.StyleSheet.create({
3343
3454
  flex: 1,
3344
3455
  minWidth: 0
3345
3456
  },
3457
+ rangeTrigger: {
3458
+ paddingVertical: 0,
3459
+ paddingHorizontal: 0,
3460
+ borderRadius: 15,
3461
+ gap: 0
3462
+ },
3463
+ rangeTriggerHorizontal: {
3464
+ height: 78,
3465
+ flexDirection: "row"
3466
+ },
3467
+ rangeTriggerVertical: {
3468
+ height: 156,
3469
+ flexDirection: "column"
3470
+ },
3471
+ rangeField: {
3472
+ flex: 1,
3473
+ alignSelf: "stretch",
3474
+ minWidth: 0,
3475
+ justifyContent: "center",
3476
+ gap: 8,
3477
+ paddingVertical: 12,
3478
+ paddingHorizontal: 16
3479
+ },
3480
+ rangeLabel: {
3481
+ ...datePickerTypography.rangeLabel,
3482
+ color: colors.whiteAlpha60
3483
+ },
3484
+ rangeValueRow: {
3485
+ minWidth: 0,
3486
+ flexDirection: "row",
3487
+ alignItems: "center",
3488
+ justifyContent: "space-between",
3489
+ gap: 12
3490
+ },
3491
+ rangeDate: {
3492
+ ...datePickerTypography.rangeDate,
3493
+ flexShrink: 1,
3494
+ color: colors.white
3495
+ },
3496
+ rangeTimeWrap: {
3497
+ flexShrink: 0,
3498
+ flexDirection: "row",
3499
+ alignItems: "center",
3500
+ gap: 3
3501
+ },
3502
+ rangeTime: {
3503
+ ...datePickerTypography.rangeTime,
3504
+ color: colors.lightGrey
3505
+ },
3506
+ rangeDividerHorizontal: {
3507
+ width: 1,
3508
+ alignSelf: "stretch",
3509
+ backgroundColor: colors.grey500
3510
+ },
3511
+ rangeDividerVertical: {
3512
+ height: 1,
3513
+ alignSelf: "stretch",
3514
+ backgroundColor: colors.grey500
3515
+ },
3346
3516
  iconSlot: {
3347
3517
  width: ICON_SIZE7,
3348
3518
  height: ICON_SIZE7,
@@ -3370,6 +3540,9 @@ var styles12 = reactNative.StyleSheet.create({
3370
3540
  }
3371
3541
  })
3372
3542
  },
3543
+ rangeMenu: {
3544
+ width: RANGE_TRIGGER_WIDTH
3545
+ },
3373
3546
  calendarHeader: {
3374
3547
  height: 36,
3375
3548
  flexDirection: "row",