@scripso-homepad/ui 0.4.10 → 0.4.11

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.
Files changed (37) hide show
  1. package/dist/index.cjs +122 -43
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +2 -2
  4. package/dist/index.d.ts +2 -2
  5. package/dist/index.js +124 -45
  6. package/dist/index.js.map +1 -1
  7. package/dist/web/index.cjs +45 -33
  8. package/dist/web/index.cjs.map +1 -1
  9. package/dist/web/index.d.cts +2 -1
  10. package/dist/web/index.d.ts +2 -1
  11. package/dist/web/index.js +45 -33
  12. package/dist/web/index.js.map +1 -1
  13. package/package.json +3 -2
  14. package/src/components/Calendar.tsx +10 -2
  15. package/src/components/DatePicker.tsx +3 -3
  16. package/src/components/Select.tsx +133 -38
  17. package/src/theme/select.ts +1 -1
  18. package/src/utils/calendarDays.ts +15 -6
  19. package/src/web/components/Badge.tsx +1 -1
  20. package/src/web/components/ConfirmModal.tsx +2 -2
  21. package/src/web/components/Drawer.stories.tsx +7 -7
  22. package/src/web/components/Drawer.tsx +2 -2
  23. package/src/web/components/HistoryTimeline.tsx +2 -2
  24. package/src/web/components/Modal.stories.tsx +1 -1
  25. package/src/web/components/Modal.tsx +27 -10
  26. package/src/web/components/Pagination.tsx +2 -2
  27. package/src/web/components/TableActionButton.tsx +1 -1
  28. package/src/web/components/TableActionsMenu.tsx +1 -1
  29. package/src/web/components/TableIconText.tsx +1 -1
  30. package/src/web/components/Toaster.stories.tsx +7 -7
  31. package/src/web/components/table/constants.ts +2 -2
  32. package/src/web/layout/AppHeader.tsx +1 -1
  33. package/src/web/layout/BuildingSelect.tsx +2 -2
  34. package/src/web/layout/DashboardLayout.stories.tsx +1 -1
  35. package/src/web/layout/SidebarNavItem.tsx +1 -1
  36. package/src/web/layout/SidebarUserCard.tsx +3 -3
  37. package/src/web/styles/typography.css +99 -0
package/dist/index.d.cts CHANGED
@@ -164,12 +164,12 @@ type CalendarBaseProps = {
164
164
  type CalendarSingleProps = CalendarBaseProps & {
165
165
  mode?: "single";
166
166
  value?: Date;
167
- onChange?: (date: Date) => void;
167
+ onChange?: (date: Date | undefined) => void;
168
168
  };
169
169
  type CalendarRangeProps = CalendarBaseProps & {
170
170
  mode: "range";
171
171
  value?: DateRange;
172
- onChange?: (range: DateRange) => void;
172
+ onChange?: (range: DateRange | undefined) => void;
173
173
  };
174
174
  type CalendarProps = CalendarSingleProps | CalendarRangeProps;
175
175
  declare function Calendar(props: CalendarProps): react.JSX.Element;
package/dist/index.d.ts CHANGED
@@ -164,12 +164,12 @@ type CalendarBaseProps = {
164
164
  type CalendarSingleProps = CalendarBaseProps & {
165
165
  mode?: "single";
166
166
  value?: Date;
167
- onChange?: (date: Date) => void;
167
+ onChange?: (date: Date | undefined) => void;
168
168
  };
169
169
  type CalendarRangeProps = CalendarBaseProps & {
170
170
  mode: "range";
171
171
  value?: DateRange;
172
- onChange?: (range: DateRange) => void;
172
+ onChange?: (range: DateRange | undefined) => void;
173
173
  };
174
174
  type CalendarProps = CalendarSingleProps | CalendarRangeProps;
175
175
  declare function Calendar(props: CalendarProps): react.JSX.Element;
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
- import { spacing, colors, fontSize, fontWeight, fonts, radii, INPUT_ICON_GAP, useApplyWebClassName, resolveInputVisualState, Label, getInputFieldStyles, inputFieldMetrics } from './chunk-YSDLHEJ7.js';
1
+ import { spacing, colors, fontWeight, fontSize, fonts, radii, INPUT_ICON_GAP, useApplyWebClassName, resolveInputVisualState, Label, getInputFieldStyles, inputFieldMetrics } from './chunk-YSDLHEJ7.js';
2
2
  export { Button, Input, Label, brand, buttonTypography, colors, emeraldGreen, fontSize, fontWeight, fonts, labelTypography, navy, radii, rubyRed, shadows, spacing, stormGray } from './chunk-YSDLHEJ7.js';
3
3
  import { createContext, useRef, useState, useMemo, useEffect, useLayoutEffect, useContext, isValidElement, cloneElement } from 'react';
4
- import { Platform, StyleSheet, Animated, Easing, Pressable, Text, View, Modal, ScrollView, TextInput, Dimensions } from 'react-native';
4
+ import { Platform, StyleSheet, Animated, Easing, View, Pressable, Text, Modal, ScrollView, TextInput, Dimensions } from 'react-native';
5
5
  import Svg2, { Path } from 'react-native-svg';
6
6
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
7
 
@@ -53,7 +53,7 @@ var selectLabelTypography = {
53
53
  fontFamily: fonts.sans,
54
54
  fontSize: fontSize.sm,
55
55
  fontWeight: fontWeight.medium,
56
- lineHeight: fontSize.sm,
56
+ lineHeight: 16,
57
57
  letterSpacing: 0,
58
58
  color: colors.slateBlue
59
59
  };
@@ -373,6 +373,86 @@ function renderSelectIcon(icon, color) {
373
373
  }
374
374
  return icon;
375
375
  }
376
+ function resolveWebTextNode(ref) {
377
+ if (Platform.OS !== "web") {
378
+ return null;
379
+ }
380
+ const node = ref.current;
381
+ return node instanceof HTMLElement ? node : null;
382
+ }
383
+ function syncTruncatedNativeTitle(ref, label) {
384
+ const element = resolveWebTextNode(ref);
385
+ if (!element) {
386
+ return;
387
+ }
388
+ if (element.scrollWidth > element.clientWidth) {
389
+ element.setAttribute("title", label);
390
+ return;
391
+ }
392
+ element.removeAttribute("title");
393
+ }
394
+ function clearNativeTitle(ref) {
395
+ resolveWebTextNode(ref)?.removeAttribute("title");
396
+ }
397
+ function SelectOptionItem({
398
+ option,
399
+ compact,
400
+ optionHeight,
401
+ isSelected,
402
+ isHighlighted,
403
+ isLast,
404
+ selectableIndex,
405
+ onHighlight,
406
+ onSelect
407
+ }) {
408
+ const labelRef = useRef(null);
409
+ return /* @__PURE__ */ jsx(
410
+ Pressable,
411
+ {
412
+ accessibilityRole: "button",
413
+ accessibilityState: { disabled: option.disabled, selected: isSelected },
414
+ disabled: option.disabled,
415
+ onPress: () => {
416
+ if (!option.disabled) {
417
+ onSelect(option.value);
418
+ }
419
+ },
420
+ onHoverIn: () => {
421
+ if (!option.disabled && selectableIndex >= 0) {
422
+ onHighlight(selectableIndex);
423
+ }
424
+ syncTruncatedNativeTitle(labelRef, option.label);
425
+ },
426
+ onHoverOut: () => {
427
+ clearNativeTitle(labelRef);
428
+ },
429
+ style: [
430
+ selectDropdownMetrics.option,
431
+ compact && styles.optionCompact,
432
+ { height: optionHeight, minHeight: optionHeight, maxHeight: optionHeight },
433
+ isSelected && selectDropdownMetrics.optionSelected,
434
+ compact && isSelected && styles.optionSelectedCompact,
435
+ isHighlighted && !isSelected && !option.disabled ? selectDropdownMetrics.optionHighlighted : null,
436
+ !isLast && styles.optionSpacing,
437
+ option.disabled && styles.optionDisabled
438
+ ],
439
+ children: /* @__PURE__ */ jsx(
440
+ Text,
441
+ {
442
+ ref: labelRef,
443
+ style: [
444
+ selectDropdownMetrics.optionLabel,
445
+ styles.optionLabel,
446
+ isSelected && selectDropdownMetrics.optionLabelSelected,
447
+ option.disabled && styles.optionLabelDisabled
448
+ ],
449
+ numberOfLines: 1,
450
+ children: option.label
451
+ }
452
+ )
453
+ }
454
+ );
455
+ }
376
456
  var useIsomorphicLayoutEffect = typeof window === "undefined" ? useEffect : useLayoutEffect;
377
457
  function normalizeSelectedValues(multiple, value) {
378
458
  if (multiple) {
@@ -505,6 +585,11 @@ function Select({
505
585
  onValueChange?.(nextValues);
506
586
  return;
507
587
  }
588
+ if (selectedValues.includes(nextValue)) {
589
+ onValueChange?.("");
590
+ closeMenu();
591
+ return;
592
+ }
508
593
  onValueChange?.(nextValue);
509
594
  closeMenu();
510
595
  }
@@ -514,43 +599,17 @@ function Select({
514
599
  const isHighlighted = selectableIndex === highlightedIndex;
515
600
  const isLast = index === options.length - 1;
516
601
  return /* @__PURE__ */ jsx(
517
- Pressable,
602
+ SelectOptionItem,
518
603
  {
519
- accessibilityRole: "button",
520
- accessibilityState: { disabled: option.disabled, selected: isSelected },
521
- disabled: option.disabled,
522
- onPress: () => {
523
- if (!option.disabled) {
524
- handleSelect(option.value);
525
- }
526
- },
527
- onHoverIn: () => {
528
- if (!option.disabled && selectableIndex >= 0) {
529
- setHighlightedIndex(selectableIndex);
530
- }
531
- },
532
- style: [
533
- selectDropdownMetrics.option,
534
- compact && styles.optionCompact,
535
- { height: optionHeight, minHeight: optionHeight, maxHeight: optionHeight },
536
- isSelected && selectDropdownMetrics.optionSelected,
537
- compact && isSelected && styles.optionSelectedCompact,
538
- isHighlighted && !isSelected && !option.disabled ? selectDropdownMetrics.optionHighlighted : null,
539
- !isLast && styles.optionSpacing,
540
- option.disabled && styles.optionDisabled
541
- ],
542
- children: /* @__PURE__ */ jsx(
543
- Text,
544
- {
545
- style: [
546
- selectDropdownMetrics.optionLabel,
547
- isSelected && selectDropdownMetrics.optionLabelSelected,
548
- option.disabled && styles.optionLabelDisabled
549
- ],
550
- numberOfLines: 1,
551
- children: option.label
552
- }
553
- )
604
+ option,
605
+ compact,
606
+ optionHeight,
607
+ isSelected,
608
+ isHighlighted,
609
+ isLast,
610
+ selectableIndex,
611
+ onHighlight: setHighlightedIndex,
612
+ onSelect: handleSelect
554
613
  },
555
614
  option.value
556
615
  );
@@ -685,6 +744,14 @@ var styles = StyleSheet.create({
685
744
  optionDisabled: {
686
745
  opacity: 0.5
687
746
  },
747
+ optionLabel: {
748
+ minWidth: 0,
749
+ ...Platform.OS === "web" ? {
750
+ overflow: "hidden",
751
+ textOverflow: "ellipsis",
752
+ whiteSpace: "nowrap"
753
+ } : null
754
+ },
688
755
  optionLabelDisabled: {
689
756
  color: colors.stormGray300
690
757
  },
@@ -1513,17 +1580,24 @@ function isInDateRange(date, start, end) {
1513
1580
  }
1514
1581
  function selectRangeDate(clicked, current) {
1515
1582
  const clickedDate = stripTime(clicked);
1516
- if (!current?.start || current.end) {
1583
+ if (!current?.start) {
1517
1584
  return { start: clickedDate };
1518
1585
  }
1519
1586
  const start = stripTime(current.start);
1520
- if (isSameDay(clickedDate, start)) {
1587
+ const end = current.end ? stripTime(current.end) : void 0;
1588
+ if (!end) {
1589
+ if (isSameDay(clickedDate, start)) {
1590
+ return void 0;
1591
+ }
1592
+ if (isBeforeDay(clickedDate, start)) {
1593
+ return { start: clickedDate };
1594
+ }
1521
1595
  return { start, end: clickedDate };
1522
1596
  }
1523
- if (isBeforeDay(clickedDate, start)) {
1524
- return { start: clickedDate };
1597
+ if (isSameDay(clickedDate, end)) {
1598
+ return void 0;
1525
1599
  }
1526
- return { start, end: clickedDate };
1600
+ return { start: clickedDate };
1527
1601
  }
1528
1602
  function isSameDay(left, right) {
1529
1603
  return left.getFullYear() === right.getFullYear() && left.getMonth() === right.getMonth() && left.getDate() === right.getDate();
@@ -2015,6 +2089,11 @@ function Calendar(props) {
2015
2089
  rangeProps.onChange?.(selectRangeDate(date, rangeProps.value));
2016
2090
  return;
2017
2091
  }
2092
+ const currentValue = singleProps?.value;
2093
+ if (currentValue && isSameDay(date, currentValue)) {
2094
+ singleProps?.onChange?.(void 0);
2095
+ return;
2096
+ }
2018
2097
  singleProps?.onChange?.(date);
2019
2098
  }
2020
2099
  const headerIsPressable = pickerView === "days" || pickerView === "months";
@@ -2263,7 +2342,7 @@ function DatePicker(props) {
2263
2342
  return;
2264
2343
  }
2265
2344
  props.onChange?.(range);
2266
- if (closeOnRangeComplete && range.end) {
2345
+ if (closeOnRangeComplete && range?.end) {
2267
2346
  closePicker();
2268
2347
  }
2269
2348
  }