@shortstravelmgmt/component-lib 0.1.12 → 0.1.14

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.js CHANGED
@@ -262,7 +262,7 @@ const Datepicker = React.forwardRef(({ size = 'md', label, helperText, error, fu
262
262
  });
263
263
  Datepicker.displayName = 'Datepicker';
264
264
 
265
- var styles$17 = {"wrapper":"Input-module_wrapper__-8ija","fullWidth":"Input-module_fullWidth__xXOvN","label":"Input-module_label__t4LH-","inputWrapper":"Input-module_inputWrapper__U4EEd","error":"Input-module_error__fT9Sb","disabled":"Input-module_disabled__3tnIE","sm":"Input-module_sm__lGHP-","md":"Input-module_md__pReoW","lg":"Input-module_lg__iqqov","input":"Input-module_input__PeHY6","icon":"Input-module_icon__jkJiF","textarea":"Input-module_textarea__ZgdBz","helperText":"Input-module_helperText__eKsC8","errorText":"Input-module_errorText__xoiKP"};
265
+ var styles$17 = {"wrapper":"Input-module_wrapper__-8ija","fullWidth":"Input-module_fullWidth__xXOvN","label":"Input-module_label__t4LH-","inputWrapper":"Input-module_inputWrapper__U4EEd","error":"Input-module_error__fT9Sb","disabled":"Input-module_disabled__3tnIE","xs":"Input-module_xs__p7BuD","sm":"Input-module_sm__lGHP-","md":"Input-module_md__pReoW","lg":"Input-module_lg__iqqov","input":"Input-module_input__PeHY6","icon":"Input-module_icon__jkJiF","textarea":"Input-module_textarea__ZgdBz","helperText":"Input-module_helperText__eKsC8","errorText":"Input-module_errorText__xoiKP"};
266
266
 
267
267
  /**
268
268
  * Input component for text entry.
@@ -457,12 +457,13 @@ const Toggle = ({ checked, onChange, disabled = false, size = 'md', label, label
457
457
  return toggleElement;
458
458
  };
459
459
 
460
- var styles$_ = {"wrapper":"Tooltip-module_wrapper__9SUwl","tooltip":"Tooltip-module_tooltip__KQ7km","fadeIn":"Tooltip-module_fadeIn__dL8S5","content":"Tooltip-module_content__kO8yx","dark":"Tooltip-module_dark__Y66ss","light":"Tooltip-module_light__mItfR","top":"Tooltip-module_top__1jrIn","bottom":"Tooltip-module_bottom__99YBc","left":"Tooltip-module_left__ZNd1H","right":"Tooltip-module_right__r0j5Q","arrow":"Tooltip-module_arrow__qcKWx","arrowTop":"Tooltip-module_arrowTop__k13dt","arrowBottom":"Tooltip-module_arrowBottom__FP-w2","arrowLeft":"Tooltip-module_arrowLeft__7T1uO","arrowRight":"Tooltip-module_arrowRight__FbPdB"};
460
+ var styles$_ = {"wrapper":"Tooltip-module_wrapper__9SUwl","tooltip":"Tooltip-module_tooltip__KQ7km","fadeIn":"Tooltip-module_fadeIn__dL8S5","content":"Tooltip-module_content__kO8yx","dark":"Tooltip-module_dark__Y66ss","light":"Tooltip-module_light__mItfR","semantic":"Tooltip-module_semantic__shhec","primary":"Tooltip-module_primary__no1LJ","secondary":"Tooltip-module_secondary__HEoKK","success":"Tooltip-module_success__EG2f-","warning":"Tooltip-module_warning__1zoqE","error":"Tooltip-module_error__Nn6y6","top":"Tooltip-module_top__1jrIn","bottom":"Tooltip-module_bottom__99YBc","left":"Tooltip-module_left__ZNd1H","right":"Tooltip-module_right__r0j5Q","arrow":"Tooltip-module_arrow__qcKWx","arrowTop":"Tooltip-module_arrowTop__k13dt","arrowBottom":"Tooltip-module_arrowBottom__FP-w2","arrowLeft":"Tooltip-module_arrowLeft__7T1uO","arrowRight":"Tooltip-module_arrowRight__FbPdB"};
461
461
 
462
462
  const Tooltip = ({ content, children, position = 'top', variant = 'dark', delay = 200, disabled = false, className = '', }) => {
463
463
  const [isVisible, setIsVisible] = React.useState(false);
464
464
  const [actualPosition, setActualPosition] = React.useState(position);
465
465
  const timeoutRef = React.useRef(null);
466
+ const touchTimeoutRef = React.useRef(null);
466
467
  const tooltipRef = React.useRef(null);
467
468
  const triggerRef = React.useRef(null);
468
469
  const checkBounds = () => {
@@ -514,14 +515,27 @@ const Tooltip = ({ content, children, position = 'top', variant = 'dark', delay
514
515
  const handleBlur = () => {
515
516
  setIsVisible(false);
516
517
  };
518
+ const handleTouchStart = () => {
519
+ if (disabled)
520
+ return;
521
+ if (touchTimeoutRef.current)
522
+ clearTimeout(touchTimeoutRef.current);
523
+ setIsVisible(true);
524
+ };
525
+ const handleTouchEnd = () => {
526
+ touchTimeoutRef.current = setTimeout(() => setIsVisible(false), 2000);
527
+ };
517
528
  React.useEffect(() => {
518
529
  return () => {
519
530
  if (timeoutRef.current) {
520
531
  clearTimeout(timeoutRef.current);
521
532
  }
533
+ if (touchTimeoutRef.current) {
534
+ clearTimeout(touchTimeoutRef.current);
535
+ }
522
536
  };
523
537
  }, []);
524
- return (jsxRuntime.jsxs("div", { ref: triggerRef, className: `${styles$_.wrapper} ${className}`, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onFocus: handleFocus, onBlur: handleBlur, children: [children, isVisible && content && (jsxRuntime.jsxs("div", { ref: tooltipRef, className: `${styles$_.tooltip} ${styles$_[actualPosition]} ${styles$_[variant]}`, role: "tooltip", children: [jsxRuntime.jsx("div", { className: styles$_.content, children: content }), jsxRuntime.jsx("div", { className: `${styles$_.arrow} ${styles$_[`arrow${actualPosition.charAt(0).toUpperCase()}${actualPosition.slice(1)}`]}` })] }))] }));
538
+ return (jsxRuntime.jsxs("div", { ref: triggerRef, className: `${styles$_.wrapper} ${className}`, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onFocus: handleFocus, onBlur: handleBlur, onTouchStart: handleTouchStart, onTouchEnd: handleTouchEnd, children: [children, isVisible && content && (jsxRuntime.jsxs("div", { ref: tooltipRef, className: `${styles$_.tooltip} ${styles$_[actualPosition]} ${styles$_[variant]} ${!['dark', 'light'].includes(variant) ? styles$_.semantic : ''}`, role: "tooltip", children: [jsxRuntime.jsx("div", { className: styles$_.content, children: content }), jsxRuntime.jsx("div", { className: `${styles$_.arrow} ${styles$_[`arrow${actualPosition.charAt(0).toUpperCase()}${actualPosition.slice(1)}`]}` })] }))] }));
525
539
  };
526
540
 
527
541
  var styles$Z = {"service":"TravelServiceIcon-module_service__-4EZb","code":"TravelServiceIcon-module_code__vElzI","multi":"TravelServiceIcon-module_multi__nqZLM","multiIndicator":"TravelServiceIcon-module_multiIndicator__KJF1L"};
@@ -1093,7 +1107,7 @@ const TeamHeader = ({ title: suppliedTitle, teamCode, teamName, pretitle = 'Team
1093
1107
  window.location.href = backHref;
1094
1108
  }
1095
1109
  };
1096
- return (jsxRuntime.jsxs("div", { className: headerClasses, children: [jsxRuntime.jsxs("div", { className: styles$F.left, children: [(backHref || onBack) && (jsxRuntime.jsx("button", { type: "button", className: styles$F.backButton, onClick: handleBack, "aria-label": "Go back", children: jsxRuntime.jsx(BackIcon, {}) })), jsxRuntime.jsxs("div", { className: styles$F.titles, children: [pretitle && jsxRuntime.jsx("span", { className: styles$F.pretitle, children: pretitle }), jsxRuntime.jsxs("h1", { className: styles$F.title, children: [title, "\u00A0"] })] })] }), actions && (jsxRuntime.jsx("div", { className: styles$F.actions, children: actions }))] }));
1110
+ return (jsxRuntime.jsxs("div", { className: headerClasses, "data-test": "team-header", children: [jsxRuntime.jsxs("div", { className: styles$F.left, children: [(backHref || onBack) && (jsxRuntime.jsx("button", { type: "button", className: styles$F.backButton, onClick: handleBack, "aria-label": "Go back", "data-test": "team-header-back", children: jsxRuntime.jsx(BackIcon, {}) })), jsxRuntime.jsxs("div", { className: styles$F.titles, children: [pretitle && jsxRuntime.jsx("span", { className: styles$F.pretitle, children: pretitle }), jsxRuntime.jsxs("h1", { className: styles$F.title, children: [title, "\u00A0"] })] })] }), actions && (jsxRuntime.jsx("div", { className: styles$F.actions, children: actions }))] }));
1097
1111
  };
1098
1112
  const DEFAULT_TABS$1 = [
1099
1113
  { id: 'profile', label: 'Profile' },
@@ -1102,7 +1116,7 @@ const DEFAULT_TABS$1 = [
1102
1116
  { id: 'user-access', label: 'User Access' },
1103
1117
  ];
1104
1118
  /** Router-agnostic counterpart of Hub's team-management submenu. */
1105
- const TeamSubMenu = ({ tabs = DEFAULT_TABS$1, activeTab, onTabChange, className = '' }) => (jsxRuntime.jsx("nav", { className: [styles$F.subMenu, className].filter(Boolean).join(' '), "aria-label": "Team management sections", children: tabs.map((tab) => (jsxRuntime.jsx("button", { type: "button", className: activeTab === tab.id ? styles$F.activeTab : '', "aria-current": activeTab === tab.id ? 'page' : undefined, onClick: () => onTabChange?.(tab.id), children: tab.label }, tab.id))) }));
1119
+ const TeamSubMenu = ({ tabs = DEFAULT_TABS$1, activeTab, onTabChange, className = '' }) => (jsxRuntime.jsx("nav", { className: [styles$F.subMenu, className].filter(Boolean).join(' '), "aria-label": "Team management sections", "data-test": "team-management-tabs", children: tabs.map((tab) => (jsxRuntime.jsx("button", { type: "button", className: activeTab === tab.id ? styles$F.activeTab : '', "aria-current": activeTab === tab.id ? 'page' : undefined, "data-test": `team-management-tab-${tab.id}`, onClick: () => onTabChange?.(tab.id), children: tab.label }, tab.id))) }));
1106
1120
  TeamHeader.displayName = 'TeamHeader';
1107
1121
  TeamSubMenu.displayName = 'TeamSubMenu';
1108
1122
 
@@ -1740,7 +1754,7 @@ const TeamCard = ({ title = 'Administer Teams', icon, teams, onTeamSelect, class
1740
1754
  styles$m.card,
1741
1755
  className,
1742
1756
  ].filter(Boolean).join(' ');
1743
- return (jsxRuntime.jsxs("div", { className: cardClasses, children: [jsxRuntime.jsxs("div", { className: styles$m.header, children: [jsxRuntime.jsx("span", { className: styles$m.icon, children: icon || jsxRuntime.jsx(UsersIcon, {}) }), jsxRuntime.jsx("h3", { className: styles$m.title, children: title })] }), jsxRuntime.jsxs("div", { className: styles$m.body, children: [jsxRuntime.jsx("div", { className: styles$m.tabs, children: TEAM_GROUPS.map(({ label, key }) => (jsxRuntime.jsx("button", { type: "button", onClick: () => setActiveTab(key), className: `${styles$m.tab} ${activeTab === key ? styles$m.tabActive : ''}`, children: label }, label))) }), jsxRuntime.jsxs("div", { className: styles$m.list, children: [filteredTeams.map((team) => (jsxRuntime.jsxs("button", { type: "button", className: styles$m.teamItem, onClick: () => onTeamSelect?.(team), children: [jsxRuntime.jsx("span", { className: styles$m.teamCode, style: { backgroundColor: getTeamColor(team.code) }, children: team.code }), jsxRuntime.jsx("span", { className: styles$m.teamName, children: team.description }), jsxRuntime.jsx("span", { className: styles$m.chevron, children: jsxRuntime.jsx(ChevronRightIcon, {}) })] }, team.id))), filteredTeams.length === 0 && (jsxRuntime.jsx("div", { className: styles$m.empty, children: "No teams found" }))] })] })] }));
1757
+ return (jsxRuntime.jsxs("div", { className: cardClasses, "data-test": "team-card", children: [jsxRuntime.jsxs("div", { className: styles$m.header, children: [jsxRuntime.jsx("span", { className: styles$m.icon, children: icon || jsxRuntime.jsx(UsersIcon, {}) }), jsxRuntime.jsx("h3", { className: styles$m.title, children: title })] }), jsxRuntime.jsxs("div", { className: styles$m.body, children: [jsxRuntime.jsx("div", { className: styles$m.tabs, children: TEAM_GROUPS.map(({ label, key }) => (jsxRuntime.jsx("button", { type: "button", onClick: () => setActiveTab(key), className: `${styles$m.tab} ${activeTab === key ? styles$m.tabActive : ''}`, "data-test": `team-card-filter-${key ?? 'all'}`, children: label }, label))) }), jsxRuntime.jsxs("div", { className: styles$m.list, children: [filteredTeams.map((team) => (jsxRuntime.jsxs("button", { type: "button", className: styles$m.teamItem, "data-test": `team-card-team-${team.id}`, onClick: () => onTeamSelect?.(team), children: [jsxRuntime.jsx("span", { className: styles$m.teamCode, style: { backgroundColor: getTeamColor(team.code) }, children: team.code }), jsxRuntime.jsx("span", { className: styles$m.teamName, children: team.description }), jsxRuntime.jsx("span", { className: styles$m.chevron, children: jsxRuntime.jsx(ChevronRightIcon, {}) })] }, team.id))), filteredTeams.length === 0 && (jsxRuntime.jsx("div", { className: styles$m.empty, children: "No teams found" }))] })] })] }));
1744
1758
  };
1745
1759
  TeamCard.displayName = 'TeamCard';
1746
1760
 
@@ -1751,7 +1765,9 @@ const CONTACTS_TOOLTIP = 'Only contacts listed in the School Contacts are availa
1751
1765
  const ContactPicker = ({ title, contacts, selectedId, onSelect, allowNone = true, compact = false, disabled = false, loading = false, dataTestId, }) => {
1752
1766
  const [open, setOpen] = React.useState(false);
1753
1767
  const [search, setSearch] = React.useState('');
1768
+ const [selecting, setSelecting] = React.useState(false);
1754
1769
  const containerRef = React.useRef(null);
1770
+ const pending = loading || selecting;
1755
1771
  const selected = contacts.find((contact) => String(contact.id) === String(selectedId));
1756
1772
  const filteredContacts = React.useMemo(() => {
1757
1773
  const query = search.trim().toLowerCase();
@@ -1766,12 +1782,18 @@ const ContactPicker = ({ title, contacts, selectedId, onSelect, allowNone = true
1766
1782
  document.addEventListener('mousedown', close);
1767
1783
  return () => document.removeEventListener('mousedown', close);
1768
1784
  }, []);
1769
- const select = (id) => {
1770
- onSelect?.(id);
1771
- setOpen(false);
1772
- setSearch('');
1785
+ const select = async (id) => {
1786
+ setSelecting(true);
1787
+ try {
1788
+ await onSelect?.(id);
1789
+ }
1790
+ finally {
1791
+ setSelecting(false);
1792
+ setOpen(false);
1793
+ setSearch('');
1794
+ }
1773
1795
  };
1774
- return (jsxRuntime.jsxs("div", { className: styles$l.picker, ref: containerRef, "data-test": dataTestId, children: [jsxRuntime.jsx("div", { className: styles$l.fieldLabel, children: title }), jsxRuntime.jsxs("div", { className: [styles$l.contactSegment, compact ? styles$l.compactSegment : ''].filter(Boolean).join(' '), children: [!compact && selected && jsxRuntime.jsx(Avatar, { className: styles$l.contactAvatar, name: selected.name, size: "sm" }), jsxRuntime.jsxs("div", { className: styles$l.contactDetails, children: [jsxRuntime.jsxs("button", { type: "button", className: [styles$l.contactTrigger, !selected ? styles$l.emptyContact : '', selected?.active === false ? styles$l.inactiveContact : ''].filter(Boolean).join(' '), disabled: disabled || loading, "data-test": `${dataTestId}-trigger`, "aria-expanded": open, "aria-haspopup": "listbox", "aria-label": `${title}: ${selected?.name ?? `Select ${title}`}`, onClick: () => setOpen((current) => !current), children: [jsxRuntime.jsx("span", { children: selected?.name ?? `Select ${title}` }), selected?.active === false && (jsxRuntime.jsx(Tooltip, { content: "A contact displayed in red is no longer an active portal user and must be replaced by an active user to ensure the accurate delivery of documents and notifications.", variant: "dark", children: jsxRuntime.jsx(WarningIcon$1, { size: 16, "aria-label": "Inactive portal user" }) })), loading ? jsxRuntime.jsx(Spinner, { size: "sm", label: `Updating ${title}` }) : open ? jsxRuntime.jsx(ChevronUpIcon, { size: 16 }) : jsxRuntime.jsx(ChevronDownIcon$1, { size: 16 })] }), !compact && selected?.title && jsxRuntime.jsx("span", { className: styles$l.contactTitle, children: selected.title }), !compact && selected?.phone && jsxRuntime.jsxs("a", { href: `tel:${selected.phone}`, className: styles$l.contactLink, children: [jsxRuntime.jsx(PhoneIcon, { size: 20 }), " ", selected.phone] }), !compact && selected?.email && jsxRuntime.jsxs("a", { href: `mailto:${selected.email}`, className: styles$l.contactLink, children: [jsxRuntime.jsx(MailIcon, { size: 20 }), " ", selected.email] })] })] }), open && (jsxRuntime.jsxs("div", { className: [styles$l.contactMenu, compact ? styles$l.compactMenu : ''].filter(Boolean).join(' '), role: "listbox", "aria-label": `${title} options`, children: [jsxRuntime.jsx("div", { className: styles$l.searchRow, children: jsxRuntime.jsx(Input, { size: "sm", fullWidth: true, autoFocus: true, value: search, placeholder: "Search contacts", "aria-label": `Search ${title}`, "data-test": `${dataTestId}-search`, leftIcon: jsxRuntime.jsx(SearchIcon$1, { size: 15 }), onChange: (event) => setSearch(event.target.value) }) }), jsxRuntime.jsx("div", { className: styles$l.menuDivider }), jsxRuntime.jsxs("div", { className: styles$l.contactOptions, children: [allowNone && selected && (jsxRuntime.jsxs("button", { type: "button", className: styles$l.clearContact, "data-test": `${dataTestId}-clear`, onClick: () => select(undefined), children: [jsxRuntime.jsx("span", { className: styles$l.clearIcon, children: jsxRuntime.jsx(TrashIcon$2, { size: 16 }) }), jsxRuntime.jsxs("span", { children: ["Clear ", title] })] })), filteredContacts.map((contact) => (jsxRuntime.jsxs("button", { type: "button", role: "option", "aria-selected": false, className: styles$l.contactOption, "data-test": `${dataTestId}-option-${contact.id}`, onClick: () => select(contact.id), children: [!compact && jsxRuntime.jsx(Avatar, { className: styles$l.optionAvatar, name: contact.name, size: "sm" }), jsxRuntime.jsxs("span", { children: [jsxRuntime.jsx("strong", { children: contact.name }), contact.title && jsxRuntime.jsx("small", { children: contact.title })] })] }, contact.id))), !filteredContacts.length && jsxRuntime.jsx("div", { className: styles$l.emptyOptions, children: "No matching contacts" })] })] }))] }));
1796
+ return (jsxRuntime.jsxs("div", { className: styles$l.picker, ref: containerRef, "data-test": dataTestId, children: [jsxRuntime.jsx("div", { className: styles$l.fieldLabel, children: title }), jsxRuntime.jsxs("div", { className: [styles$l.contactSegment, compact ? styles$l.compactSegment : ''].filter(Boolean).join(' '), children: [!compact && selected && jsxRuntime.jsx(Avatar, { className: styles$l.contactAvatar, name: selected.name, size: "sm" }), jsxRuntime.jsxs("div", { className: styles$l.contactDetails, children: [jsxRuntime.jsxs("button", { type: "button", className: [styles$l.contactTrigger, !selected ? styles$l.emptyContact : '', selected?.active === false ? styles$l.inactiveContact : ''].filter(Boolean).join(' '), disabled: disabled || pending, "data-test": `${dataTestId}-trigger`, "aria-expanded": open, "aria-haspopup": "listbox", "aria-busy": pending, "aria-label": `${title}: ${selected?.name ?? `Select ${title}`}`, onClick: () => setOpen((current) => !current), children: [jsxRuntime.jsx("span", { children: selected?.name ?? `Select ${title}` }), selected?.active === false && (jsxRuntime.jsx(Tooltip, { content: "A contact displayed in red is no longer an active portal user and must be replaced by an active user to ensure the accurate delivery of documents and notifications.", position: "right", variant: "error", delay: 0, children: jsxRuntime.jsx(WarningIcon$1, { size: 16, "aria-label": "Inactive portal user" }) })), pending ? jsxRuntime.jsx(Spinner, { size: "sm", label: `Updating ${title}` }) : open ? jsxRuntime.jsx(ChevronUpIcon, { size: 16 }) : jsxRuntime.jsx(ChevronDownIcon$1, { size: 16 })] }), !compact && selected?.title && jsxRuntime.jsx("span", { className: styles$l.contactTitle, children: selected.title }), !compact && selected?.phone && jsxRuntime.jsxs("a", { href: `tel:${selected.phone}`, className: styles$l.contactLink, children: [jsxRuntime.jsx(PhoneIcon, { size: 20 }), " ", selected.phone] }), !compact && selected?.email && jsxRuntime.jsxs("a", { href: `mailto:${selected.email}`, className: styles$l.contactLink, children: [jsxRuntime.jsx(MailIcon, { size: 20 }), " ", selected.email] })] })] }), open && (jsxRuntime.jsxs("div", { className: [styles$l.contactMenu, compact ? styles$l.compactMenu : ''].filter(Boolean).join(' '), role: "listbox", "aria-label": `${title} options`, children: [jsxRuntime.jsx("div", { className: styles$l.searchRow, children: jsxRuntime.jsx(Input, { size: "xs", fullWidth: true, autoFocus: true, value: search, placeholder: "Search contacts", "aria-label": `Search ${title}`, "data-test": `${dataTestId}-search`, leftIcon: jsxRuntime.jsx(SearchIcon$1, { size: 15 }), onChange: (event) => setSearch(event.target.value) }) }), jsxRuntime.jsx("div", { className: styles$l.menuDivider }), jsxRuntime.jsxs("div", { className: styles$l.contactOptions, children: [allowNone && selected && (jsxRuntime.jsxs("button", { type: "button", className: styles$l.clearContact, "data-test": `${dataTestId}-clear`, disabled: selecting, onClick: () => void select(undefined), children: [jsxRuntime.jsx("span", { className: styles$l.clearIcon, children: jsxRuntime.jsx(TrashIcon$2, { size: 16 }) }), jsxRuntime.jsxs("span", { children: ["Clear ", title] })] })), filteredContacts.map((contact) => (jsxRuntime.jsxs("button", { type: "button", role: "option", "aria-selected": false, className: styles$l.contactOption, "data-test": `${dataTestId}-option-${contact.id}`, disabled: selecting, onClick: () => void select(contact.id), children: [jsxRuntime.jsx(Avatar, { className: styles$l.optionAvatar, name: contact.name, size: "sm" }), jsxRuntime.jsxs("span", { children: [jsxRuntime.jsx("strong", { children: contact.name }), contact.title && jsxRuntime.jsx("small", { children: contact.title })] })] }, contact.id))), !filteredContacts.length && jsxRuntime.jsx("div", { className: styles$l.emptyOptions, children: "No matching contacts" })] })] }))] }));
1775
1797
  };
1776
1798
  const TeamContactsPanel = ({ contacts, value, onChange, disabled = false, loading = {}, dataTestId = 'team-contacts', className = '', }) => {
1777
1799
  const ccContactIds = Array.from({ length: 4 }, (_, index) => value.ccContactIds?.[index]);
@@ -1780,23 +1802,23 @@ const TeamContactsPanel = ({ contacts, value, onChange, disabled = false, loadin
1780
1802
  next[index] = id;
1781
1803
  onChange?.({ ...value, ccContactIds: next });
1782
1804
  };
1783
- return (jsxRuntime.jsxs("div", { className: [styles$l.panel, className].filter(Boolean).join(' '), "data-test": dataTestId, children: [jsxRuntime.jsx(Alert, { variant: "warning", children: CONTACTS_NOTE }), jsxRuntime.jsx(Module, { title: (jsxRuntime.jsxs("span", { className: styles$l.moduleTitle, children: [jsxRuntime.jsx("span", { children: "Team Contacts" }), jsxRuntime.jsx(Tooltip, { content: CONTACTS_TOOLTIP, position: "bottom", variant: "light", children: jsxRuntime.jsx("button", { type: "button", className: styles$l.infoButton, "aria-label": "Team contacts information", children: jsxRuntime.jsx(InfoIcon$1, { size: 16 }) }) })] })), useToggle: false, className: styles$l.contactsModule, bodyClassName: styles$l.moduleBody, children: jsxRuntime.jsxs("div", { className: styles$l.contactsGrid, children: [jsxRuntime.jsxs("div", { className: styles$l.primaryGrid, children: [jsxRuntime.jsx(ContactPicker, { title: "Primary Contact", contacts: contacts, selectedId: value.primaryContactId, allowNone: false, disabled: disabled, loading: loading.primary, dataTestId: `${dataTestId}-primary`, onSelect: (primaryContactId) => onChange?.({ ...value, primaryContactId }) }), jsxRuntime.jsx("div", { className: styles$l.verticalDivider }), jsxRuntime.jsx(ContactPicker, { title: "Secondary Contact", contacts: contacts, selectedId: value.secondaryContactId, disabled: disabled, loading: loading.secondary, dataTestId: `${dataTestId}-secondary`, onSelect: (secondaryContactId) => onChange?.({ ...value, secondaryContactId }) })] }), jsxRuntime.jsx("div", { className: styles$l.verticalDivider }), jsxRuntime.jsx("div", { className: styles$l.ccGrid, children: ccContactIds.map((contactId, index) => (jsxRuntime.jsx(ContactPicker, { title: `CC Contact ${index + 1}`, contacts: contacts, selectedId: contactId, compact: true, disabled: disabled, loading: loading.cc?.[index], dataTestId: `${dataTestId}-cc-${index + 1}`, onSelect: (id) => updateCC(index, id) }, index))) })] }) })] }));
1805
+ return (jsxRuntime.jsxs("div", { className: [styles$l.panel, className].filter(Boolean).join(' '), "data-test": dataTestId, children: [jsxRuntime.jsx(Alert, { variant: "warning", children: CONTACTS_NOTE }), jsxRuntime.jsx(Module, { title: (jsxRuntime.jsxs("span", { className: styles$l.moduleTitle, children: [jsxRuntime.jsx("span", { children: "Team Contacts" }), jsxRuntime.jsx(Tooltip, { content: CONTACTS_TOOLTIP, position: "bottom", variant: "primary", delay: 0, children: jsxRuntime.jsx("button", { type: "button", className: styles$l.infoButton, "aria-label": "Team contacts information", children: jsxRuntime.jsx(InfoIcon$1, { size: 16 }) }) })] })), useToggle: false, className: styles$l.contactsModule, bodyClassName: styles$l.moduleBody, children: jsxRuntime.jsxs("div", { className: styles$l.contactsGrid, children: [jsxRuntime.jsxs("div", { className: styles$l.primaryGrid, children: [jsxRuntime.jsx(ContactPicker, { title: "Primary Contact", contacts: contacts, selectedId: value.primaryContactId, allowNone: false, disabled: disabled, loading: loading.primary, dataTestId: `${dataTestId}-primary`, onSelect: (primaryContactId) => onChange?.({ ...value, primaryContactId }) }), jsxRuntime.jsx("div", { className: styles$l.verticalDivider }), jsxRuntime.jsx(ContactPicker, { title: "Secondary Contact", contacts: contacts, selectedId: value.secondaryContactId, disabled: disabled, loading: loading.secondary, dataTestId: `${dataTestId}-secondary`, onSelect: (secondaryContactId) => onChange?.({ ...value, secondaryContactId }) })] }), jsxRuntime.jsx("div", { className: styles$l.verticalDivider }), jsxRuntime.jsx("div", { className: styles$l.ccGrid, children: ccContactIds.map((contactId, index) => (jsxRuntime.jsx(ContactPicker, { title: `CC Contact ${index + 1}`, contacts: contacts, selectedId: contactId, compact: true, disabled: disabled, loading: loading.cc?.[index], dataTestId: `${dataTestId}-cc-${index + 1}`, onSelect: (id) => updateCC(index, id) }, index))) })] }) })] }));
1784
1806
  };
1785
1807
  TeamContactsPanel.displayName = 'TeamContactsPanel';
1786
1808
 
1787
1809
  var styles$k = {"actions":"TeamScheduleActions-module_actions__OvuON","primaryRow":"TeamScheduleActions-module_primaryRow__8rwhE","tripCount":"TeamScheduleActions-module_tripCount__4axn4","seasonNavigator":"TeamScheduleActions-module_seasonNavigator__jmqeE","seasonLabel":"TeamScheduleActions-module_seasonLabel__8MtKK","secondaryRow":"TeamScheduleActions-module_secondaryRow__We2n9"};
1788
1810
 
1789
1811
  /** Exact presentational counterpart of Hub's Team Schedule action controls. */
1790
- const TeamScheduleActions = ({ isCompactView, tripCount, seasonLabel, seasonValue, seasonOptions = [], previousSeasonDisabled = false, exportDisabled = false, exporting = false, groupTravelDisabled = false, mergeDisabled = false, merging = false, onViewSchedule, onBack, onPreviousSeason, onNextSeason, onSeasonChange, onExport, onGroupTravelRequest, onMergeEvents, className = '', }) => (jsxRuntime.jsxs("div", { className: [styles$k.actions, className].filter(Boolean).join(' '), children: [jsxRuntime.jsxs("div", { className: styles$k.primaryRow, children: [!isCompactView ? (jsxRuntime.jsx(Button, { "data-test": "team-schedule-view-edit", size: "sm", onClick: onViewSchedule, children: "View/Edit Schedule" })) : (jsxRuntime.jsx(Button, { "data-test": "team-schedule-back", size: "sm", onClick: onBack, leftIcon: jsxRuntime.jsx(ChevronLeftIcon, { size: 14 }), children: "Back" })), jsxRuntime.jsxs("div", { className: styles$k.seasonNavigator, children: [jsxRuntime.jsx(Button, { variant: "secondary", size: "sm", square: true, "aria-label": "Previous Season", disabled: previousSeasonDisabled, onClick: onPreviousSeason, children: jsxRuntime.jsx(ChevronLeftIcon, { size: 18 }) }), jsxRuntime.jsxs("div", { className: styles$k.seasonLabel, children: [jsxRuntime.jsx(Button, { variant: "secondary", size: "sm", children: seasonLabel }), !!seasonOptions.length && (jsxRuntime.jsx("select", { "aria-label": "Season", value: seasonValue, onChange: (event) => onSeasonChange?.(event.target.value), children: seasonOptions.map((option) => jsxRuntime.jsx("option", { value: option.value, children: option.label }, option.value)) }))] }), jsxRuntime.jsx(Button, { variant: "secondary", size: "sm", square: true, "aria-label": "Next Season", onClick: onNextSeason, children: jsxRuntime.jsx(ChevronRightIcon$1, { size: 18 }) })] }), isCompactView && jsxRuntime.jsx(Button, { variant: "outline", size: "sm", loading: exporting, disabled: exportDisabled, rightIcon: jsxRuntime.jsx(ArrowUpRightIcon, { size: 14 }), onClick: onExport, children: "Export XLS" }), jsxRuntime.jsxs("span", { className: styles$k.tripCount, children: [tripCount, " trips displayed"] })] }), isCompactView && (jsxRuntime.jsxs("div", { className: styles$k.secondaryRow, children: [jsxRuntime.jsx(Button, { variant: "outline", size: "sm", disabled: groupTravelDisabled, onClick: onGroupTravelRequest, children: "Group Travel Request" }), jsxRuntime.jsx(Button, { variant: "outline", size: "sm", disabled: mergeDisabled, loading: merging, onClick: onMergeEvents, children: "Merge Events" })] }))] }));
1812
+ const TeamScheduleActions = ({ isCompactView, tripCount, seasonLabel, seasonValue, seasonOptions = [], previousSeasonDisabled = false, exportDisabled = false, exporting = false, groupTravelDisabled = false, mergeDisabled = false, merging = false, onViewSchedule, onBack, onPreviousSeason, onNextSeason, onSeasonChange, onExport, onGroupTravelRequest, onMergeEvents, className = '', }) => (jsxRuntime.jsxs("div", { className: [styles$k.actions, className].filter(Boolean).join(' '), "data-test": "team-schedule-actions", children: [jsxRuntime.jsxs("div", { className: styles$k.primaryRow, children: [!isCompactView ? (jsxRuntime.jsx(Button, { "data-test": "team-schedule-view-edit", size: "sm", onClick: onViewSchedule, children: "View/Edit Schedule" })) : (jsxRuntime.jsx(Button, { "data-test": "team-schedule-back", size: "sm", onClick: onBack, leftIcon: jsxRuntime.jsx(ChevronLeftIcon, { size: 14 }), children: "Back" })), jsxRuntime.jsxs("div", { className: styles$k.seasonNavigator, children: [jsxRuntime.jsx(Button, { "data-test": "team-schedule-previous-season", variant: "secondary", size: "sm", square: true, "aria-label": "Previous Season", disabled: previousSeasonDisabled, onClick: onPreviousSeason, children: jsxRuntime.jsx(ChevronLeftIcon, { size: 18 }) }), jsxRuntime.jsxs("div", { className: styles$k.seasonLabel, children: [jsxRuntime.jsx(Button, { variant: "secondary", size: "sm", children: seasonLabel }), !!seasonOptions.length && (jsxRuntime.jsx("select", { "data-test": "team-schedule-season", "aria-label": "Season", value: seasonValue, onChange: (event) => onSeasonChange?.(event.target.value), children: seasonOptions.map((option) => jsxRuntime.jsx("option", { value: option.value, children: option.label }, option.value)) }))] }), jsxRuntime.jsx(Button, { "data-test": "team-schedule-next-season", variant: "secondary", size: "sm", square: true, "aria-label": "Next Season", onClick: onNextSeason, children: jsxRuntime.jsx(ChevronRightIcon$1, { size: 18 }) })] }), isCompactView && jsxRuntime.jsx(Button, { "data-test": "team-schedule-export", variant: "outline", size: "sm", loading: exporting, disabled: exportDisabled, rightIcon: jsxRuntime.jsx(ArrowUpRightIcon, { size: 14 }), onClick: onExport, children: "Export XLS" }), jsxRuntime.jsxs("span", { className: styles$k.tripCount, "data-test": "team-schedule-trip-count", children: [tripCount, " trips displayed"] })] }), isCompactView && (jsxRuntime.jsxs("div", { className: styles$k.secondaryRow, children: [jsxRuntime.jsx(Button, { "data-test": "team-schedule-group-travel-request", variant: "outline", size: "sm", disabled: groupTravelDisabled, onClick: onGroupTravelRequest, children: "Group Travel Request" }), jsxRuntime.jsx(Button, { "data-test": "team-schedule-merge-events", variant: "outline", size: "sm", disabled: mergeDisabled, loading: merging, onClick: onMergeEvents, children: "Merge Events" })] }))] }));
1791
1813
 
1792
1814
  var styles$j = {"headers":"TeamScheduleCompactTable-module_headers__FVr2C","tripHeader":"TeamScheduleCompactTable-module_tripHeader__9vr2-","eventHeader":"TeamScheduleCompactTable-module_eventHeader__6gfwo","table":"TeamScheduleCompactTable-module_table__MdE3o","row":"TeamScheduleCompactTable-module_row__Rt0YC","trip":"TeamScheduleCompactTable-module_trip__oAUEQ","events":"TeamScheduleCompactTable-module_events__EwJi9","empty":"TeamScheduleCompactTable-module_empty__1u5HA","addRow":"TeamScheduleCompactTable-module_addRow__ejqSf"};
1793
1815
 
1794
1816
  const DEFAULT_TRIP_HEADERS = ['', 'GTR', 'Trvl Start', 'Trvl End', 'Trip Name', 'Services', ''];
1795
1817
  const DEFAULT_EVENT_HEADERS = ['', 'Event Date', 'Opponent/Host', 'Event Title', 'Hm/Awy', ''];
1796
1818
  /** Hub's two-panel compact Team Schedule shell. Editable rows remain injectable. */
1797
- const TeamScheduleCompactTable = ({ rows, tripHeaders = DEFAULT_TRIP_HEADERS, eventHeaders = DEFAULT_EVENT_HEADERS, onAddEvent, addEventDisabled = false, className = '', }) => (jsxRuntime.jsxs("div", { className: [styles$j.schedule, className].filter(Boolean).join(' '), children: [jsxRuntime.jsxs("div", { className: styles$j.headers, children: [jsxRuntime.jsx("div", { className: styles$j.tripHeader, children: tripHeaders.map((header, index) => jsxRuntime.jsx("div", { children: header }, index)) }), jsxRuntime.jsx("div", { className: styles$j.eventHeader, children: eventHeaders.map((header, index) => jsxRuntime.jsx("div", { children: header }, index)) })] }), jsxRuntime.jsx("div", { className: styles$j.table, children: !rows.length ? jsxRuntime.jsx("div", { className: styles$j.empty, children: "No data available." }) : rows.map((row) => (jsxRuntime.jsxs("div", { className: styles$j.row, children: [jsxRuntime.jsx("div", { className: styles$j.trip, children: row.trip }), jsxRuntime.jsx("div", { className: styles$j.events, children: row.events })] }, row.id))) }), jsxRuntime.jsx("div", { className: styles$j.addRow, children: jsxRuntime.jsxs("button", { type: "button", disabled: addEventDisabled, onClick: onAddEvent, children: ["Add Event ", jsxRuntime.jsx(PlusIcon$2, { size: 16 })] }) })] }));
1819
+ const TeamScheduleCompactTable = ({ rows, tripHeaders = DEFAULT_TRIP_HEADERS, eventHeaders = DEFAULT_EVENT_HEADERS, onAddEvent, addEventDisabled = false, className = '', }) => (jsxRuntime.jsxs("div", { className: [styles$j.schedule, className].filter(Boolean).join(' '), "data-test": "team-schedule-editor", children: [jsxRuntime.jsxs("div", { className: styles$j.headers, children: [jsxRuntime.jsx("div", { className: styles$j.tripHeader, children: tripHeaders.map((header, index) => jsxRuntime.jsx("div", { children: header }, index)) }), jsxRuntime.jsx("div", { className: styles$j.eventHeader, children: eventHeaders.map((header, index) => jsxRuntime.jsx("div", { children: header }, index)) })] }), jsxRuntime.jsx("div", { className: styles$j.table, children: !rows.length ? jsxRuntime.jsx("div", { className: styles$j.empty, "data-test": "team-schedule-empty", children: "No data available." }) : rows.map((row) => (jsxRuntime.jsxs("div", { className: styles$j.row, children: [jsxRuntime.jsx("div", { className: styles$j.trip, children: row.trip }), jsxRuntime.jsx("div", { className: styles$j.events, children: row.events })] }, row.id))) }), jsxRuntime.jsx("div", { className: styles$j.addRow, children: jsxRuntime.jsxs("button", { type: "button", disabled: addEventDisabled, onClick: onAddEvent, "data-test": "team-schedule-add-event", children: ["Add Event ", jsxRuntime.jsx(PlusIcon$2, { size: 16 })] }) })] }));
1798
1820
 
1799
- var styles$i = {"table":"TeamScheduleExpandedTable-module_table__hmnHI","header":"TeamScheduleExpandedTable-module_header__7IWV-","row":"TeamScheduleExpandedTable-module_row__9MyHH","body":"TeamScheduleExpandedTable-module_body__NsvB3","cell":"TeamScheduleExpandedTable-module_cell__kgawH","tripLink":"TeamScheduleExpandedTable-module_tripLink__lYoi8","mobileLabel":"TeamScheduleExpandedTable-module_mobileLabel__J6apm","empty":"TeamScheduleExpandedTable-module_empty__d9Afo"};
1821
+ var styles$i = {"table":"TeamScheduleExpandedTable-module_table__hmnHI","header":"TeamScheduleExpandedTable-module_header__7IWV-","row":"TeamScheduleExpandedTable-module_row__9MyHH","body":"TeamScheduleExpandedTable-module_body__NsvB3","cell":"TeamScheduleExpandedTable-module_cell__kgawH","tripLink":"TeamScheduleExpandedTable-module_tripLink__lYoi8","tripSummary":"TeamScheduleExpandedTable-module_tripSummary__XHSok","dueDates":"TeamScheduleExpandedTable-module_dueDates__vpCRG","dueDatesLabel":"TeamScheduleExpandedTable-module_dueDatesLabel__YwM9s","dueDate":"TeamScheduleExpandedTable-module_dueDate__8exi9","mobileLabel":"TeamScheduleExpandedTable-module_mobileLabel__J6apm","empty":"TeamScheduleExpandedTable-module_empty__d9Afo"};
1800
1822
 
1801
1823
  const parseLocalDate = (value) => {
1802
1824
  if (!value)
@@ -1823,6 +1845,11 @@ const formatTeamScheduleTravelDates = (startValue, endValue) => {
1823
1845
  return `${formatDate$1(start)} - ${formatDate$1(end)}`;
1824
1846
  return `${formatDate$1(start, false)} - ${end.getDate()}, ${end.getFullYear()}`;
1825
1847
  };
1848
+ const formatTeamScheduleDueDate = (value) => {
1849
+ const date = parseLocalDate(value);
1850
+ return date ? date.toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' }) : value;
1851
+ };
1852
+ const TripSummary = ({ row, onTripClick }) => (jsxRuntime.jsxs("div", { className: styles$i.tripSummary, children: [jsxRuntime.jsx("button", { type: "button", className: styles$i.tripLink, "data-test": `team-schedule-trip-${row.masterTripGUID}`, onClick: () => onTripClick?.(row), children: row.tripName }), !!row.dueDates?.length && (jsxRuntime.jsxs("div", { className: styles$i.dueDates, "data-test": `team-schedule-due-dates-${row.masterTripGUID}`, "aria-label": `Due dates for ${row.tripName}`, children: [jsxRuntime.jsx("span", { className: styles$i.dueDatesLabel, children: "Due Dates" }), row.dueDates.map((dueDate, index) => (jsxRuntime.jsxs("div", { className: styles$i.dueDate, "data-test": `team-schedule-due-date-${dueDate.id ?? index}`, children: [jsxRuntime.jsx("span", { children: dueDate.title }), jsxRuntime.jsx("time", { dateTime: dueDate.date, children: formatTeamScheduleDueDate(dueDate.date) })] }, dueDate.id ?? `${dueDate.title}-${dueDate.date}`)))] }))] }));
1826
1853
  const RunningIcon = () => (jsxRuntime.jsxs("svg", { viewBox: "0 0 32 32", width: "16", height: "16", fill: "currentColor", "aria-hidden": "true", children: [jsxRuntime.jsx("circle", { cx: "21", cy: "5", r: "3" }), jsxRuntime.jsx("path", { d: "m18.5 9.3-4.2 4.2-4.1-2.1-1.4 2.8 5.9 3 3.3-3.2 2.3 5.2-5.2 3.2 1.7 2.6 7.4-4.6-3.3-7.2 2.4-2.4 2.1 3.1 2.6-1.8-4.2-6.4zM10 18.8 5.6 26H9l4-6.2z" })] }));
1827
1854
  const GroundIcon = () => (jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", width: "16", height: "16", fill: "none", stroke: "currentColor", strokeWidth: "1.8", "aria-hidden": "true", children: [jsxRuntime.jsx("rect", { x: "4", y: "3", width: "16", height: "16", rx: "2" }), jsxRuntime.jsx("path", { d: "M4 13h16M8 7h3m2 0h3M7 19v2m10-2v2" })] }));
1828
1855
  const headers = [
@@ -1854,7 +1881,7 @@ const TeamScheduleExpandedTable = ({ rows, teamCode, onTripClick, emptyMessage =
1854
1881
  const values = [
1855
1882
  teamCode ?? row.sportCode ?? '–',
1856
1883
  formatTeamScheduleTravelDates(row.travelStartDate, row.travelEndDate),
1857
- jsxRuntime.jsx("button", { type: "button", className: styles$i.tripLink, onClick: () => onTripClick?.(row), children: row.tripName }),
1884
+ jsxRuntime.jsx(TripSummary, { row: row, onTripClick: onTripClick }),
1858
1885
  row.airSegment,
1859
1886
  row.groundSegment,
1860
1887
  row.hotelSegment,
@@ -2077,7 +2104,7 @@ const sportColor = (sportCode) => {
2077
2104
  return '#D1C1C3';
2078
2105
  return '#8AC6D9';
2079
2106
  };
2080
- const TeamTravelCalendarToolbar = ({ duration, label = '', navigation, onDurationChange, onToday, onPrevious, onNext, className = '', }) => (jsxRuntime.jsxs("div", { className: [styles$g.toolbar, className].filter(Boolean).join(' '), children: [jsxRuntime.jsx("button", { type: "button", className: styles$g.todayButton, onClick: onToday, children: "Today" }), jsxRuntime.jsx(SegmentedSelector, { value: duration, size: "sm", ariaLabel: "Calendar duration", onChange: (value) => onDurationChange?.(value), options: [{ id: 'month', label: 'Month' }, { id: 'week', label: 'Week' }] }), navigation ?? (jsxRuntime.jsxs("div", { className: styles$g.periodNavigation, children: [jsxRuntime.jsx("button", { type: "button", className: styles$g.navigationButton, "aria-label": `Previous ${duration}`, onClick: onPrevious, children: jsxRuntime.jsx(ChevronLeft$1, {}) }), jsxRuntime.jsx("button", { type: "button", className: styles$g.periodButton, children: label }), jsxRuntime.jsx("button", { type: "button", className: styles$g.navigationButton, "aria-label": `Next ${duration}`, onClick: onNext, children: jsxRuntime.jsx(ChevronRight$2, {}) })] }))] }));
2107
+ const TeamTravelCalendarToolbar = ({ duration, label = '', navigation, onDurationChange, onToday, onPrevious, onNext, className = '', }) => (jsxRuntime.jsxs("div", { className: [styles$g.toolbar, className].filter(Boolean).join(' '), "data-test": "calendar-toolbar", children: [jsxRuntime.jsx("button", { type: "button", className: styles$g.todayButton, onClick: onToday, "data-test": "calendar-today", children: "Today" }), jsxRuntime.jsx(SegmentedSelector, { value: duration, size: "sm", ariaLabel: "Calendar duration", onChange: (value) => onDurationChange?.(value), options: [{ id: 'month', label: 'Month' }, { id: 'week', label: 'Week' }] }), navigation ?? (jsxRuntime.jsxs("div", { className: styles$g.periodNavigation, children: [jsxRuntime.jsx("button", { type: "button", className: styles$g.navigationButton, "aria-label": `Previous ${duration}`, onClick: onPrevious, children: jsxRuntime.jsx(ChevronLeft$1, {}) }), jsxRuntime.jsx("button", { type: "button", className: styles$g.periodButton, children: label }), jsxRuntime.jsx("button", { type: "button", className: styles$g.navigationButton, "aria-label": `Next ${duration}`, onClick: onNext, children: jsxRuntime.jsx(ChevronRight$2, {}) })] }))] }));
2081
2108
  const getVisibleDates = (activeDate, duration) => {
2082
2109
  const active = parseDate(activeDate);
2083
2110
  if (duration === 'week') {
@@ -3237,6 +3264,7 @@ exports.UsersIcon = UsersIcon$1;
3237
3264
  exports.WarningIcon = WarningIcon$1;
3238
3265
  exports.XIcon = XIcon;
3239
3266
  exports.formatCompactTripCost = formatCompactTripCost;
3267
+ exports.formatTeamScheduleDueDate = formatTeamScheduleDueDate;
3240
3268
  exports.formatTeamScheduleTravelDates = formatTeamScheduleTravelDates;
3241
3269
  exports.getTeamTravelCalendarPeriodLabel = getTeamTravelCalendarPeriodLabel;
3242
3270
  exports.isTravelDueDateCompleted = isTravelDueDateCompleted;