@shortstravelmgmt/component-lib 0.1.12 → 0.1.13

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.d.ts CHANGED
@@ -224,7 +224,7 @@ declare const Icons: {
224
224
  };
225
225
  type IconName = keyof typeof Icons;
226
226
 
227
- type InputSize = 'sm' | 'md' | 'lg';
227
+ type InputSize = 'xs' | 'sm' | 'md' | 'lg';
228
228
  interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size'> {
229
229
  /** Size of the input */
230
230
  size?: InputSize;
@@ -423,7 +423,7 @@ interface ToggleProps {
423
423
  declare const Toggle: React__default.FC<ToggleProps>;
424
424
 
425
425
  type TooltipPosition = 'top' | 'bottom' | 'left' | 'right';
426
- type TooltipVariant = 'dark' | 'light';
426
+ type TooltipVariant = 'dark' | 'light' | 'primary' | 'secondary' | 'success' | 'warning' | 'error';
427
427
  interface TooltipProps {
428
428
  /** Tooltip content */
429
429
  content: React__default.ReactNode;
package/dist/index.esm.js CHANGED
@@ -260,7 +260,7 @@ const Datepicker = forwardRef(({ size = 'md', label, helperText, error, fullWidt
260
260
  });
261
261
  Datepicker.displayName = 'Datepicker';
262
262
 
263
- 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"};
263
+ 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"};
264
264
 
265
265
  /**
266
266
  * Input component for text entry.
@@ -455,12 +455,13 @@ const Toggle = ({ checked, onChange, disabled = false, size = 'md', label, label
455
455
  return toggleElement;
456
456
  };
457
457
 
458
- 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"};
458
+ 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"};
459
459
 
460
460
  const Tooltip = ({ content, children, position = 'top', variant = 'dark', delay = 200, disabled = false, className = '', }) => {
461
461
  const [isVisible, setIsVisible] = useState(false);
462
462
  const [actualPosition, setActualPosition] = useState(position);
463
463
  const timeoutRef = useRef(null);
464
+ const touchTimeoutRef = useRef(null);
464
465
  const tooltipRef = useRef(null);
465
466
  const triggerRef = useRef(null);
466
467
  const checkBounds = () => {
@@ -512,14 +513,27 @@ const Tooltip = ({ content, children, position = 'top', variant = 'dark', delay
512
513
  const handleBlur = () => {
513
514
  setIsVisible(false);
514
515
  };
516
+ const handleTouchStart = () => {
517
+ if (disabled)
518
+ return;
519
+ if (touchTimeoutRef.current)
520
+ clearTimeout(touchTimeoutRef.current);
521
+ setIsVisible(true);
522
+ };
523
+ const handleTouchEnd = () => {
524
+ touchTimeoutRef.current = setTimeout(() => setIsVisible(false), 2000);
525
+ };
515
526
  useEffect(() => {
516
527
  return () => {
517
528
  if (timeoutRef.current) {
518
529
  clearTimeout(timeoutRef.current);
519
530
  }
531
+ if (touchTimeoutRef.current) {
532
+ clearTimeout(touchTimeoutRef.current);
533
+ }
520
534
  };
521
535
  }, []);
522
- return (jsxs("div", { ref: triggerRef, className: `${styles$_.wrapper} ${className}`, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onFocus: handleFocus, onBlur: handleBlur, children: [children, isVisible && content && (jsxs("div", { ref: tooltipRef, className: `${styles$_.tooltip} ${styles$_[actualPosition]} ${styles$_[variant]}`, role: "tooltip", children: [jsx("div", { className: styles$_.content, children: content }), jsx("div", { className: `${styles$_.arrow} ${styles$_[`arrow${actualPosition.charAt(0).toUpperCase()}${actualPosition.slice(1)}`]}` })] }))] }));
536
+ return (jsxs("div", { ref: triggerRef, className: `${styles$_.wrapper} ${className}`, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onFocus: handleFocus, onBlur: handleBlur, onTouchStart: handleTouchStart, onTouchEnd: handleTouchEnd, children: [children, isVisible && content && (jsxs("div", { ref: tooltipRef, className: `${styles$_.tooltip} ${styles$_[actualPosition]} ${styles$_[variant]} ${!['dark', 'light'].includes(variant) ? styles$_.semantic : ''}`, role: "tooltip", children: [jsx("div", { className: styles$_.content, children: content }), jsx("div", { className: `${styles$_.arrow} ${styles$_[`arrow${actualPosition.charAt(0).toUpperCase()}${actualPosition.slice(1)}`]}` })] }))] }));
523
537
  };
524
538
 
525
539
  var styles$Z = {"service":"TravelServiceIcon-module_service__-4EZb","code":"TravelServiceIcon-module_code__vElzI","multi":"TravelServiceIcon-module_multi__nqZLM","multiIndicator":"TravelServiceIcon-module_multiIndicator__KJF1L"};
@@ -1091,7 +1105,7 @@ const TeamHeader = ({ title: suppliedTitle, teamCode, teamName, pretitle = 'Team
1091
1105
  window.location.href = backHref;
1092
1106
  }
1093
1107
  };
1094
- return (jsxs("div", { className: headerClasses, children: [jsxs("div", { className: styles$F.left, children: [(backHref || onBack) && (jsx("button", { type: "button", className: styles$F.backButton, onClick: handleBack, "aria-label": "Go back", children: jsx(BackIcon, {}) })), jsxs("div", { className: styles$F.titles, children: [pretitle && jsx("span", { className: styles$F.pretitle, children: pretitle }), jsxs("h1", { className: styles$F.title, children: [title, "\u00A0"] })] })] }), actions && (jsx("div", { className: styles$F.actions, children: actions }))] }));
1108
+ return (jsxs("div", { className: headerClasses, "data-test": "team-header", children: [jsxs("div", { className: styles$F.left, children: [(backHref || onBack) && (jsx("button", { type: "button", className: styles$F.backButton, onClick: handleBack, "aria-label": "Go back", "data-test": "team-header-back", children: jsx(BackIcon, {}) })), jsxs("div", { className: styles$F.titles, children: [pretitle && jsx("span", { className: styles$F.pretitle, children: pretitle }), jsxs("h1", { className: styles$F.title, children: [title, "\u00A0"] })] })] }), actions && (jsx("div", { className: styles$F.actions, children: actions }))] }));
1095
1109
  };
1096
1110
  const DEFAULT_TABS$1 = [
1097
1111
  { id: 'profile', label: 'Profile' },
@@ -1100,7 +1114,7 @@ const DEFAULT_TABS$1 = [
1100
1114
  { id: 'user-access', label: 'User Access' },
1101
1115
  ];
1102
1116
  /** Router-agnostic counterpart of Hub's team-management submenu. */
1103
- const TeamSubMenu = ({ tabs = DEFAULT_TABS$1, activeTab, onTabChange, className = '' }) => (jsx("nav", { className: [styles$F.subMenu, className].filter(Boolean).join(' '), "aria-label": "Team management sections", children: tabs.map((tab) => (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))) }));
1117
+ const TeamSubMenu = ({ tabs = DEFAULT_TABS$1, activeTab, onTabChange, className = '' }) => (jsx("nav", { className: [styles$F.subMenu, className].filter(Boolean).join(' '), "aria-label": "Team management sections", "data-test": "team-management-tabs", children: tabs.map((tab) => (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))) }));
1104
1118
  TeamHeader.displayName = 'TeamHeader';
1105
1119
  TeamSubMenu.displayName = 'TeamSubMenu';
1106
1120
 
@@ -1738,7 +1752,7 @@ const TeamCard = ({ title = 'Administer Teams', icon, teams, onTeamSelect, class
1738
1752
  styles$m.card,
1739
1753
  className,
1740
1754
  ].filter(Boolean).join(' ');
1741
- return (jsxs("div", { className: cardClasses, children: [jsxs("div", { className: styles$m.header, children: [jsx("span", { className: styles$m.icon, children: icon || jsx(UsersIcon, {}) }), jsx("h3", { className: styles$m.title, children: title })] }), jsxs("div", { className: styles$m.body, children: [jsx("div", { className: styles$m.tabs, children: TEAM_GROUPS.map(({ label, key }) => (jsx("button", { type: "button", onClick: () => setActiveTab(key), className: `${styles$m.tab} ${activeTab === key ? styles$m.tabActive : ''}`, children: label }, label))) }), jsxs("div", { className: styles$m.list, children: [filteredTeams.map((team) => (jsxs("button", { type: "button", className: styles$m.teamItem, onClick: () => onTeamSelect?.(team), children: [jsx("span", { className: styles$m.teamCode, style: { backgroundColor: getTeamColor(team.code) }, children: team.code }), jsx("span", { className: styles$m.teamName, children: team.description }), jsx("span", { className: styles$m.chevron, children: jsx(ChevronRightIcon, {}) })] }, team.id))), filteredTeams.length === 0 && (jsx("div", { className: styles$m.empty, children: "No teams found" }))] })] })] }));
1755
+ return (jsxs("div", { className: cardClasses, "data-test": "team-card", children: [jsxs("div", { className: styles$m.header, children: [jsx("span", { className: styles$m.icon, children: icon || jsx(UsersIcon, {}) }), jsx("h3", { className: styles$m.title, children: title })] }), jsxs("div", { className: styles$m.body, children: [jsx("div", { className: styles$m.tabs, children: TEAM_GROUPS.map(({ label, key }) => (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))) }), jsxs("div", { className: styles$m.list, children: [filteredTeams.map((team) => (jsxs("button", { type: "button", className: styles$m.teamItem, "data-test": `team-card-team-${team.id}`, onClick: () => onTeamSelect?.(team), children: [jsx("span", { className: styles$m.teamCode, style: { backgroundColor: getTeamColor(team.code) }, children: team.code }), jsx("span", { className: styles$m.teamName, children: team.description }), jsx("span", { className: styles$m.chevron, children: jsx(ChevronRightIcon, {}) })] }, team.id))), filteredTeams.length === 0 && (jsx("div", { className: styles$m.empty, children: "No teams found" }))] })] })] }));
1742
1756
  };
1743
1757
  TeamCard.displayName = 'TeamCard';
1744
1758
 
@@ -1749,7 +1763,9 @@ const CONTACTS_TOOLTIP = 'Only contacts listed in the School Contacts are availa
1749
1763
  const ContactPicker = ({ title, contacts, selectedId, onSelect, allowNone = true, compact = false, disabled = false, loading = false, dataTestId, }) => {
1750
1764
  const [open, setOpen] = useState(false);
1751
1765
  const [search, setSearch] = useState('');
1766
+ const [selecting, setSelecting] = useState(false);
1752
1767
  const containerRef = useRef(null);
1768
+ const pending = loading || selecting;
1753
1769
  const selected = contacts.find((contact) => String(contact.id) === String(selectedId));
1754
1770
  const filteredContacts = useMemo(() => {
1755
1771
  const query = search.trim().toLowerCase();
@@ -1764,12 +1780,18 @@ const ContactPicker = ({ title, contacts, selectedId, onSelect, allowNone = true
1764
1780
  document.addEventListener('mousedown', close);
1765
1781
  return () => document.removeEventListener('mousedown', close);
1766
1782
  }, []);
1767
- const select = (id) => {
1768
- onSelect?.(id);
1769
- setOpen(false);
1770
- setSearch('');
1783
+ const select = async (id) => {
1784
+ setSelecting(true);
1785
+ try {
1786
+ await onSelect?.(id);
1787
+ }
1788
+ finally {
1789
+ setSelecting(false);
1790
+ setOpen(false);
1791
+ setSearch('');
1792
+ }
1771
1793
  };
1772
- return (jsxs("div", { className: styles$l.picker, ref: containerRef, "data-test": dataTestId, children: [jsx("div", { className: styles$l.fieldLabel, children: title }), jsxs("div", { className: [styles$l.contactSegment, compact ? styles$l.compactSegment : ''].filter(Boolean).join(' '), children: [!compact && selected && jsx(Avatar, { className: styles$l.contactAvatar, name: selected.name, size: "sm" }), jsxs("div", { className: styles$l.contactDetails, children: [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: [jsx("span", { children: selected?.name ?? `Select ${title}` }), selected?.active === false && (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: jsx(WarningIcon$1, { size: 16, "aria-label": "Inactive portal user" }) })), loading ? jsx(Spinner, { size: "sm", label: `Updating ${title}` }) : open ? jsx(ChevronUpIcon, { size: 16 }) : jsx(ChevronDownIcon$1, { size: 16 })] }), !compact && selected?.title && jsx("span", { className: styles$l.contactTitle, children: selected.title }), !compact && selected?.phone && jsxs("a", { href: `tel:${selected.phone}`, className: styles$l.contactLink, children: [jsx(PhoneIcon, { size: 20 }), " ", selected.phone] }), !compact && selected?.email && jsxs("a", { href: `mailto:${selected.email}`, className: styles$l.contactLink, children: [jsx(MailIcon, { size: 20 }), " ", selected.email] })] })] }), open && (jsxs("div", { className: [styles$l.contactMenu, compact ? styles$l.compactMenu : ''].filter(Boolean).join(' '), role: "listbox", "aria-label": `${title} options`, children: [jsx("div", { className: styles$l.searchRow, children: jsx(Input, { size: "sm", fullWidth: true, autoFocus: true, value: search, placeholder: "Search contacts", "aria-label": `Search ${title}`, "data-test": `${dataTestId}-search`, leftIcon: jsx(SearchIcon$1, { size: 15 }), onChange: (event) => setSearch(event.target.value) }) }), jsx("div", { className: styles$l.menuDivider }), jsxs("div", { className: styles$l.contactOptions, children: [allowNone && selected && (jsxs("button", { type: "button", className: styles$l.clearContact, "data-test": `${dataTestId}-clear`, onClick: () => select(undefined), children: [jsx("span", { className: styles$l.clearIcon, children: jsx(TrashIcon$2, { size: 16 }) }), jsxs("span", { children: ["Clear ", title] })] })), filteredContacts.map((contact) => (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 && jsx(Avatar, { className: styles$l.optionAvatar, name: contact.name, size: "sm" }), jsxs("span", { children: [jsx("strong", { children: contact.name }), contact.title && jsx("small", { children: contact.title })] })] }, contact.id))), !filteredContacts.length && jsx("div", { className: styles$l.emptyOptions, children: "No matching contacts" })] })] }))] }));
1794
+ return (jsxs("div", { className: styles$l.picker, ref: containerRef, "data-test": dataTestId, children: [jsx("div", { className: styles$l.fieldLabel, children: title }), jsxs("div", { className: [styles$l.contactSegment, compact ? styles$l.compactSegment : ''].filter(Boolean).join(' '), children: [!compact && selected && jsx(Avatar, { className: styles$l.contactAvatar, name: selected.name, size: "sm" }), jsxs("div", { className: styles$l.contactDetails, children: [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: [jsx("span", { children: selected?.name ?? `Select ${title}` }), selected?.active === false && (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: jsx(WarningIcon$1, { size: 16, "aria-label": "Inactive portal user" }) })), pending ? jsx(Spinner, { size: "sm", label: `Updating ${title}` }) : open ? jsx(ChevronUpIcon, { size: 16 }) : jsx(ChevronDownIcon$1, { size: 16 })] }), !compact && selected?.title && jsx("span", { className: styles$l.contactTitle, children: selected.title }), !compact && selected?.phone && jsxs("a", { href: `tel:${selected.phone}`, className: styles$l.contactLink, children: [jsx(PhoneIcon, { size: 20 }), " ", selected.phone] }), !compact && selected?.email && jsxs("a", { href: `mailto:${selected.email}`, className: styles$l.contactLink, children: [jsx(MailIcon, { size: 20 }), " ", selected.email] })] })] }), open && (jsxs("div", { className: [styles$l.contactMenu, compact ? styles$l.compactMenu : ''].filter(Boolean).join(' '), role: "listbox", "aria-label": `${title} options`, children: [jsx("div", { className: styles$l.searchRow, children: jsx(Input, { size: "xs", fullWidth: true, autoFocus: true, value: search, placeholder: "Search contacts", "aria-label": `Search ${title}`, "data-test": `${dataTestId}-search`, leftIcon: jsx(SearchIcon$1, { size: 15 }), onChange: (event) => setSearch(event.target.value) }) }), jsx("div", { className: styles$l.menuDivider }), jsxs("div", { className: styles$l.contactOptions, children: [allowNone && selected && (jsxs("button", { type: "button", className: styles$l.clearContact, "data-test": `${dataTestId}-clear`, disabled: selecting, onClick: () => void select(undefined), children: [jsx("span", { className: styles$l.clearIcon, children: jsx(TrashIcon$2, { size: 16 }) }), jsxs("span", { children: ["Clear ", title] })] })), filteredContacts.map((contact) => (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: [jsx(Avatar, { className: styles$l.optionAvatar, name: contact.name, size: "sm" }), jsxs("span", { children: [jsx("strong", { children: contact.name }), contact.title && jsx("small", { children: contact.title })] })] }, contact.id))), !filteredContacts.length && jsx("div", { className: styles$l.emptyOptions, children: "No matching contacts" })] })] }))] }));
1773
1795
  };
1774
1796
  const TeamContactsPanel = ({ contacts, value, onChange, disabled = false, loading = {}, dataTestId = 'team-contacts', className = '', }) => {
1775
1797
  const ccContactIds = Array.from({ length: 4 }, (_, index) => value.ccContactIds?.[index]);
@@ -1778,21 +1800,21 @@ const TeamContactsPanel = ({ contacts, value, onChange, disabled = false, loadin
1778
1800
  next[index] = id;
1779
1801
  onChange?.({ ...value, ccContactIds: next });
1780
1802
  };
1781
- return (jsxs("div", { className: [styles$l.panel, className].filter(Boolean).join(' '), "data-test": dataTestId, children: [jsx(Alert, { variant: "warning", children: CONTACTS_NOTE }), jsx(Module, { title: (jsxs("span", { className: styles$l.moduleTitle, children: [jsx("span", { children: "Team Contacts" }), jsx(Tooltip, { content: CONTACTS_TOOLTIP, position: "bottom", variant: "light", children: jsx("button", { type: "button", className: styles$l.infoButton, "aria-label": "Team contacts information", children: jsx(InfoIcon$1, { size: 16 }) }) })] })), useToggle: false, className: styles$l.contactsModule, bodyClassName: styles$l.moduleBody, children: jsxs("div", { className: styles$l.contactsGrid, children: [jsxs("div", { className: styles$l.primaryGrid, children: [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 }) }), jsx("div", { className: styles$l.verticalDivider }), jsx(ContactPicker, { title: "Secondary Contact", contacts: contacts, selectedId: value.secondaryContactId, disabled: disabled, loading: loading.secondary, dataTestId: `${dataTestId}-secondary`, onSelect: (secondaryContactId) => onChange?.({ ...value, secondaryContactId }) })] }), jsx("div", { className: styles$l.verticalDivider }), jsx("div", { className: styles$l.ccGrid, children: ccContactIds.map((contactId, index) => (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))) })] }) })] }));
1803
+ return (jsxs("div", { className: [styles$l.panel, className].filter(Boolean).join(' '), "data-test": dataTestId, children: [jsx(Alert, { variant: "warning", children: CONTACTS_NOTE }), jsx(Module, { title: (jsxs("span", { className: styles$l.moduleTitle, children: [jsx("span", { children: "Team Contacts" }), jsx(Tooltip, { content: CONTACTS_TOOLTIP, position: "bottom", variant: "primary", delay: 0, children: jsx("button", { type: "button", className: styles$l.infoButton, "aria-label": "Team contacts information", children: jsx(InfoIcon$1, { size: 16 }) }) })] })), useToggle: false, className: styles$l.contactsModule, bodyClassName: styles$l.moduleBody, children: jsxs("div", { className: styles$l.contactsGrid, children: [jsxs("div", { className: styles$l.primaryGrid, children: [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 }) }), jsx("div", { className: styles$l.verticalDivider }), jsx(ContactPicker, { title: "Secondary Contact", contacts: contacts, selectedId: value.secondaryContactId, disabled: disabled, loading: loading.secondary, dataTestId: `${dataTestId}-secondary`, onSelect: (secondaryContactId) => onChange?.({ ...value, secondaryContactId }) })] }), jsx("div", { className: styles$l.verticalDivider }), jsx("div", { className: styles$l.ccGrid, children: ccContactIds.map((contactId, index) => (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))) })] }) })] }));
1782
1804
  };
1783
1805
  TeamContactsPanel.displayName = 'TeamContactsPanel';
1784
1806
 
1785
1807
  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"};
1786
1808
 
1787
1809
  /** Exact presentational counterpart of Hub's Team Schedule action controls. */
1788
- 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 = '', }) => (jsxs("div", { className: [styles$k.actions, className].filter(Boolean).join(' '), children: [jsxs("div", { className: styles$k.primaryRow, children: [!isCompactView ? (jsx(Button, { "data-test": "team-schedule-view-edit", size: "sm", onClick: onViewSchedule, children: "View/Edit Schedule" })) : (jsx(Button, { "data-test": "team-schedule-back", size: "sm", onClick: onBack, leftIcon: jsx(ChevronLeftIcon, { size: 14 }), children: "Back" })), jsxs("div", { className: styles$k.seasonNavigator, children: [jsx(Button, { variant: "secondary", size: "sm", square: true, "aria-label": "Previous Season", disabled: previousSeasonDisabled, onClick: onPreviousSeason, children: jsx(ChevronLeftIcon, { size: 18 }) }), jsxs("div", { className: styles$k.seasonLabel, children: [jsx(Button, { variant: "secondary", size: "sm", children: seasonLabel }), !!seasonOptions.length && (jsx("select", { "aria-label": "Season", value: seasonValue, onChange: (event) => onSeasonChange?.(event.target.value), children: seasonOptions.map((option) => jsx("option", { value: option.value, children: option.label }, option.value)) }))] }), jsx(Button, { variant: "secondary", size: "sm", square: true, "aria-label": "Next Season", onClick: onNextSeason, children: jsx(ChevronRightIcon$1, { size: 18 }) })] }), isCompactView && jsx(Button, { variant: "outline", size: "sm", loading: exporting, disabled: exportDisabled, rightIcon: jsx(ArrowUpRightIcon, { size: 14 }), onClick: onExport, children: "Export XLS" }), jsxs("span", { className: styles$k.tripCount, children: [tripCount, " trips displayed"] })] }), isCompactView && (jsxs("div", { className: styles$k.secondaryRow, children: [jsx(Button, { variant: "outline", size: "sm", disabled: groupTravelDisabled, onClick: onGroupTravelRequest, children: "Group Travel Request" }), jsx(Button, { variant: "outline", size: "sm", disabled: mergeDisabled, loading: merging, onClick: onMergeEvents, children: "Merge Events" })] }))] }));
1810
+ 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 = '', }) => (jsxs("div", { className: [styles$k.actions, className].filter(Boolean).join(' '), "data-test": "team-schedule-actions", children: [jsxs("div", { className: styles$k.primaryRow, children: [!isCompactView ? (jsx(Button, { "data-test": "team-schedule-view-edit", size: "sm", onClick: onViewSchedule, children: "View/Edit Schedule" })) : (jsx(Button, { "data-test": "team-schedule-back", size: "sm", onClick: onBack, leftIcon: jsx(ChevronLeftIcon, { size: 14 }), children: "Back" })), jsxs("div", { className: styles$k.seasonNavigator, children: [jsx(Button, { "data-test": "team-schedule-previous-season", variant: "secondary", size: "sm", square: true, "aria-label": "Previous Season", disabled: previousSeasonDisabled, onClick: onPreviousSeason, children: jsx(ChevronLeftIcon, { size: 18 }) }), jsxs("div", { className: styles$k.seasonLabel, children: [jsx(Button, { variant: "secondary", size: "sm", children: seasonLabel }), !!seasonOptions.length && (jsx("select", { "data-test": "team-schedule-season", "aria-label": "Season", value: seasonValue, onChange: (event) => onSeasonChange?.(event.target.value), children: seasonOptions.map((option) => jsx("option", { value: option.value, children: option.label }, option.value)) }))] }), jsx(Button, { "data-test": "team-schedule-next-season", variant: "secondary", size: "sm", square: true, "aria-label": "Next Season", onClick: onNextSeason, children: jsx(ChevronRightIcon$1, { size: 18 }) })] }), isCompactView && jsx(Button, { "data-test": "team-schedule-export", variant: "outline", size: "sm", loading: exporting, disabled: exportDisabled, rightIcon: jsx(ArrowUpRightIcon, { size: 14 }), onClick: onExport, children: "Export XLS" }), jsxs("span", { className: styles$k.tripCount, "data-test": "team-schedule-trip-count", children: [tripCount, " trips displayed"] })] }), isCompactView && (jsxs("div", { className: styles$k.secondaryRow, children: [jsx(Button, { "data-test": "team-schedule-group-travel-request", variant: "outline", size: "sm", disabled: groupTravelDisabled, onClick: onGroupTravelRequest, children: "Group Travel Request" }), jsx(Button, { "data-test": "team-schedule-merge-events", variant: "outline", size: "sm", disabled: mergeDisabled, loading: merging, onClick: onMergeEvents, children: "Merge Events" })] }))] }));
1789
1811
 
1790
1812
  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"};
1791
1813
 
1792
1814
  const DEFAULT_TRIP_HEADERS = ['', 'GTR', 'Trvl Start', 'Trvl End', 'Trip Name', 'Services', ''];
1793
1815
  const DEFAULT_EVENT_HEADERS = ['', 'Event Date', 'Opponent/Host', 'Event Title', 'Hm/Awy', ''];
1794
1816
  /** Hub's two-panel compact Team Schedule shell. Editable rows remain injectable. */
1795
- const TeamScheduleCompactTable = ({ rows, tripHeaders = DEFAULT_TRIP_HEADERS, eventHeaders = DEFAULT_EVENT_HEADERS, onAddEvent, addEventDisabled = false, className = '', }) => (jsxs("div", { className: [styles$j.schedule, className].filter(Boolean).join(' '), children: [jsxs("div", { className: styles$j.headers, children: [jsx("div", { className: styles$j.tripHeader, children: tripHeaders.map((header, index) => jsx("div", { children: header }, index)) }), jsx("div", { className: styles$j.eventHeader, children: eventHeaders.map((header, index) => jsx("div", { children: header }, index)) })] }), jsx("div", { className: styles$j.table, children: !rows.length ? jsx("div", { className: styles$j.empty, children: "No data available." }) : rows.map((row) => (jsxs("div", { className: styles$j.row, children: [jsx("div", { className: styles$j.trip, children: row.trip }), jsx("div", { className: styles$j.events, children: row.events })] }, row.id))) }), jsx("div", { className: styles$j.addRow, children: jsxs("button", { type: "button", disabled: addEventDisabled, onClick: onAddEvent, children: ["Add Event ", jsx(PlusIcon$2, { size: 16 })] }) })] }));
1817
+ const TeamScheduleCompactTable = ({ rows, tripHeaders = DEFAULT_TRIP_HEADERS, eventHeaders = DEFAULT_EVENT_HEADERS, onAddEvent, addEventDisabled = false, className = '', }) => (jsxs("div", { className: [styles$j.schedule, className].filter(Boolean).join(' '), "data-test": "team-schedule-editor", children: [jsxs("div", { className: styles$j.headers, children: [jsx("div", { className: styles$j.tripHeader, children: tripHeaders.map((header, index) => jsx("div", { children: header }, index)) }), jsx("div", { className: styles$j.eventHeader, children: eventHeaders.map((header, index) => jsx("div", { children: header }, index)) })] }), jsx("div", { className: styles$j.table, children: !rows.length ? jsx("div", { className: styles$j.empty, "data-test": "team-schedule-empty", children: "No data available." }) : rows.map((row) => (jsxs("div", { className: styles$j.row, children: [jsx("div", { className: styles$j.trip, children: row.trip }), jsx("div", { className: styles$j.events, children: row.events })] }, row.id))) }), jsx("div", { className: styles$j.addRow, children: jsxs("button", { type: "button", disabled: addEventDisabled, onClick: onAddEvent, "data-test": "team-schedule-add-event", children: ["Add Event ", jsx(PlusIcon$2, { size: 16 })] }) })] }));
1796
1818
 
1797
1819
  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"};
1798
1820
 
@@ -2075,7 +2097,7 @@ const sportColor = (sportCode) => {
2075
2097
  return '#D1C1C3';
2076
2098
  return '#8AC6D9';
2077
2099
  };
2078
- const TeamTravelCalendarToolbar = ({ duration, label = '', navigation, onDurationChange, onToday, onPrevious, onNext, className = '', }) => (jsxs("div", { className: [styles$g.toolbar, className].filter(Boolean).join(' '), children: [jsx("button", { type: "button", className: styles$g.todayButton, onClick: onToday, children: "Today" }), jsx(SegmentedSelector, { value: duration, size: "sm", ariaLabel: "Calendar duration", onChange: (value) => onDurationChange?.(value), options: [{ id: 'month', label: 'Month' }, { id: 'week', label: 'Week' }] }), navigation ?? (jsxs("div", { className: styles$g.periodNavigation, children: [jsx("button", { type: "button", className: styles$g.navigationButton, "aria-label": `Previous ${duration}`, onClick: onPrevious, children: jsx(ChevronLeft$1, {}) }), jsx("button", { type: "button", className: styles$g.periodButton, children: label }), jsx("button", { type: "button", className: styles$g.navigationButton, "aria-label": `Next ${duration}`, onClick: onNext, children: jsx(ChevronRight$2, {}) })] }))] }));
2100
+ const TeamTravelCalendarToolbar = ({ duration, label = '', navigation, onDurationChange, onToday, onPrevious, onNext, className = '', }) => (jsxs("div", { className: [styles$g.toolbar, className].filter(Boolean).join(' '), "data-test": "calendar-toolbar", children: [jsx("button", { type: "button", className: styles$g.todayButton, onClick: onToday, "data-test": "calendar-today", children: "Today" }), jsx(SegmentedSelector, { value: duration, size: "sm", ariaLabel: "Calendar duration", onChange: (value) => onDurationChange?.(value), options: [{ id: 'month', label: 'Month' }, { id: 'week', label: 'Week' }] }), navigation ?? (jsxs("div", { className: styles$g.periodNavigation, children: [jsx("button", { type: "button", className: styles$g.navigationButton, "aria-label": `Previous ${duration}`, onClick: onPrevious, children: jsx(ChevronLeft$1, {}) }), jsx("button", { type: "button", className: styles$g.periodButton, children: label }), jsx("button", { type: "button", className: styles$g.navigationButton, "aria-label": `Next ${duration}`, onClick: onNext, children: jsx(ChevronRight$2, {}) })] }))] }));
2079
2101
  const getVisibleDates = (activeDate, duration) => {
2080
2102
  const active = parseDate(activeDate);
2081
2103
  if (duration === 'week') {