@tonyarbor/components 0.7.1 → 0.9.0

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
@@ -57,6 +57,9 @@ __export(src_exports, {
57
57
  SectionHeading: () => SectionHeading,
58
58
  SectionHeadingInteractive: () => SectionHeadingInteractive,
59
59
  SectionIcon: () => SectionIcon,
60
+ SideNavBar: () => SideNavBar,
61
+ SideNavButton: () => SideNavButton,
62
+ SideNavItem: () => SideNavItem,
60
63
  SubSectionHeading: () => SubSectionHeading,
61
64
  SubSectionInteractive: () => SubSectionInteractive,
62
65
  Table: () => Table,
@@ -83,6 +86,8 @@ var buttonStyles = {
83
86
  display: "inline-flex",
84
87
  alignItems: "center",
85
88
  justifyContent: "center",
89
+ gap: "8px",
90
+ // Consistent spacing between icon and text
86
91
  fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
87
92
  fontWeight: "500",
88
93
  borderRadius: "99px",
@@ -6749,6 +6754,423 @@ var TopNavBar = React39.forwardRef(
6749
6754
  }
6750
6755
  );
6751
6756
  TopNavBar.displayName = "TopNavBar";
6757
+
6758
+ // src/SideNavButton/SideNavButton.tsx
6759
+ var React40 = __toESM(require("react"));
6760
+ var import_lucide_react17 = require("lucide-react");
6761
+ var import_jsx_runtime40 = require("react/jsx-runtime");
6762
+ var SideNavButton = React40.forwardRef(
6763
+ ({
6764
+ icon,
6765
+ selected = false,
6766
+ focused = false,
6767
+ onClick,
6768
+ "aria-label": ariaLabel,
6769
+ className,
6770
+ style
6771
+ }, ref) => {
6772
+ const [isHovered, setIsHovered] = React40.useState(false);
6773
+ const [isActive, setIsActive] = React40.useState(false);
6774
+ const getIconColor = () => {
6775
+ if (selected) return "#0e8a0e";
6776
+ if (isActive || isHovered) return "#2f2f2f";
6777
+ return "#7e7e7e";
6778
+ };
6779
+ const getBackgroundColor = () => {
6780
+ if (selected) return "#f0faf3";
6781
+ if (isActive) return "#efefef";
6782
+ if (isHovered) return "#f8f8f8";
6783
+ return "transparent";
6784
+ };
6785
+ const buttonStyles4 = {
6786
+ display: "flex",
6787
+ alignItems: "center",
6788
+ justifyContent: "center",
6789
+ width: "42px",
6790
+ height: "42px",
6791
+ borderRadius: "99px",
6792
+ border: "none",
6793
+ backgroundColor: getBackgroundColor(),
6794
+ cursor: "pointer",
6795
+ padding: 0,
6796
+ outline: "none",
6797
+ transition: "background-color 150ms ease, box-shadow 150ms ease",
6798
+ boxShadow: focused ? "0px 0px 0px 3px #3cad51" : "none",
6799
+ ...style
6800
+ };
6801
+ const renderIcon = () => {
6802
+ const iconColor = getIconColor();
6803
+ const iconSize = 20;
6804
+ const strokeWidth = 2;
6805
+ const iconProps = {
6806
+ size: iconSize,
6807
+ color: iconColor,
6808
+ strokeWidth
6809
+ };
6810
+ switch (icon) {
6811
+ case "side-menu":
6812
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_lucide_react17.Menu, { ...iconProps });
6813
+ case "home":
6814
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_lucide_react17.Home, { ...iconProps });
6815
+ case "favourite":
6816
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_lucide_react17.Star, { ...iconProps });
6817
+ case "calendar":
6818
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_lucide_react17.Calendar, { ...iconProps });
6819
+ case "notifications":
6820
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_lucide_react17.Bell, { ...iconProps });
6821
+ case "emergency-alert":
6822
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_lucide_react17.AlertTriangle, { ...iconProps });
6823
+ case "help":
6824
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_lucide_react17.HelpCircle, { ...iconProps });
6825
+ default:
6826
+ return null;
6827
+ }
6828
+ };
6829
+ const defaultAriaLabel = icon.charAt(0).toUpperCase() + icon.slice(1);
6830
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
6831
+ "button",
6832
+ {
6833
+ ref,
6834
+ type: "button",
6835
+ className,
6836
+ style: buttonStyles4,
6837
+ onClick,
6838
+ onMouseEnter: () => setIsHovered(true),
6839
+ onMouseLeave: () => {
6840
+ setIsHovered(false);
6841
+ setIsActive(false);
6842
+ },
6843
+ onMouseDown: () => setIsActive(true),
6844
+ onMouseUp: () => setIsActive(false),
6845
+ "aria-label": ariaLabel || defaultAriaLabel,
6846
+ "aria-pressed": selected,
6847
+ children: renderIcon()
6848
+ }
6849
+ );
6850
+ }
6851
+ );
6852
+ SideNavButton.displayName = "SideNavButton";
6853
+
6854
+ // src/SideNavBar/SideNavBar.tsx
6855
+ var import_jsx_runtime41 = require("react/jsx-runtime");
6856
+ var SideNavBar = ({
6857
+ isOpen = false,
6858
+ title,
6859
+ children,
6860
+ selectedIcon,
6861
+ onIconClick,
6862
+ className,
6863
+ style
6864
+ }) => {
6865
+ const wrapperStyles6 = {
6866
+ display: "flex",
6867
+ height: "100%",
6868
+ ...style
6869
+ };
6870
+ const iconBarStyles = {
6871
+ display: "flex",
6872
+ flexDirection: "column",
6873
+ alignItems: "center",
6874
+ justifyContent: "space-between",
6875
+ backgroundColor: "#ffffff",
6876
+ padding: "8px",
6877
+ borderTopLeftRadius: "8px",
6878
+ borderBottomLeftRadius: "8px",
6879
+ height: "100%",
6880
+ width: "58px",
6881
+ boxSizing: "border-box",
6882
+ flexShrink: 0
6883
+ };
6884
+ const topSectionStyles = {
6885
+ display: "flex",
6886
+ flexDirection: "column",
6887
+ alignItems: "center",
6888
+ gap: "16px"
6889
+ };
6890
+ const dividerStyles = {
6891
+ width: "24.5px",
6892
+ height: "1px",
6893
+ backgroundColor: "#efefef"
6894
+ };
6895
+ const contentPanelStyles = {
6896
+ display: "flex",
6897
+ flexDirection: "column",
6898
+ backgroundColor: "#ffffff",
6899
+ borderLeft: "1px solid #f8f8f8",
6900
+ height: "100%",
6901
+ width: "232px",
6902
+ boxSizing: "border-box",
6903
+ flexShrink: 0,
6904
+ minWidth: 0,
6905
+ minHeight: 0
6906
+ };
6907
+ const headerStyles = {
6908
+ display: "flex",
6909
+ alignItems: "center",
6910
+ height: "62px",
6911
+ paddingLeft: "20px",
6912
+ paddingRight: "16px",
6913
+ paddingTop: "4px",
6914
+ paddingBottom: "4px",
6915
+ borderBottom: "1px solid #f8f8f8",
6916
+ boxSizing: "border-box",
6917
+ flexShrink: 0
6918
+ };
6919
+ const titleStyles2 = {
6920
+ fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
6921
+ fontSize: "13px",
6922
+ fontWeight: 600,
6923
+ color: "#2f2f2f",
6924
+ lineHeight: 1.5
6925
+ };
6926
+ const navListStyles = {
6927
+ display: "flex",
6928
+ flexDirection: "column",
6929
+ gap: "4px",
6930
+ flex: 1,
6931
+ minHeight: 0,
6932
+ overflowX: "hidden",
6933
+ overflowY: "auto",
6934
+ padding: "8px",
6935
+ boxSizing: "border-box"
6936
+ };
6937
+ const handleClick = (icon) => {
6938
+ onIconClick?.(icon);
6939
+ };
6940
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className, style: wrapperStyles6, children: [
6941
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { style: iconBarStyles, children: [
6942
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { style: topSectionStyles, children: [
6943
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
6944
+ SideNavButton,
6945
+ {
6946
+ icon: "side-menu",
6947
+ selected: selectedIcon === "side-menu",
6948
+ onClick: () => handleClick("side-menu"),
6949
+ "aria-label": "Side menu"
6950
+ }
6951
+ ),
6952
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { style: dividerStyles }),
6953
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
6954
+ SideNavButton,
6955
+ {
6956
+ icon: "favourite",
6957
+ selected: selectedIcon === "favourite",
6958
+ onClick: () => handleClick("favourite"),
6959
+ "aria-label": "Favourites"
6960
+ }
6961
+ ),
6962
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
6963
+ SideNavButton,
6964
+ {
6965
+ icon: "notifications",
6966
+ selected: selectedIcon === "notifications",
6967
+ onClick: () => handleClick("notifications"),
6968
+ "aria-label": "Notifications"
6969
+ }
6970
+ ),
6971
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
6972
+ SideNavButton,
6973
+ {
6974
+ icon: "calendar",
6975
+ selected: selectedIcon === "calendar",
6976
+ onClick: () => handleClick("calendar"),
6977
+ "aria-label": "Calendar"
6978
+ }
6979
+ ),
6980
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { style: dividerStyles }),
6981
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
6982
+ SideNavButton,
6983
+ {
6984
+ icon: "emergency-alert",
6985
+ selected: selectedIcon === "emergency-alert",
6986
+ onClick: () => handleClick("emergency-alert"),
6987
+ "aria-label": "Emergency alerts"
6988
+ }
6989
+ )
6990
+ ] }),
6991
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
6992
+ SideNavButton,
6993
+ {
6994
+ icon: "help",
6995
+ selected: selectedIcon === "help",
6996
+ onClick: () => handleClick("help"),
6997
+ "aria-label": "Help"
6998
+ }
6999
+ )
7000
+ ] }),
7001
+ isOpen && /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { style: contentPanelStyles, children: [
7002
+ title && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { style: headerStyles, children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { style: titleStyles2, children: title }) }),
7003
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { style: navListStyles, children })
7004
+ ] })
7005
+ ] });
7006
+ };
7007
+ SideNavBar.displayName = "SideNavBar";
7008
+
7009
+ // src/SideNavItem/SideNavItem.tsx
7010
+ var React41 = __toESM(require("react"));
7011
+ var import_lucide_react18 = require("lucide-react");
7012
+ var import_jsx_runtime42 = require("react/jsx-runtime");
7013
+ var SideNavItem = React41.forwardRef(
7014
+ ({
7015
+ label,
7016
+ tier = 1,
7017
+ active = false,
7018
+ hasChildren = false,
7019
+ expanded = false,
7020
+ favourited = false,
7021
+ focused = false,
7022
+ onClick,
7023
+ onExpandClick,
7024
+ onFavouriteClick,
7025
+ className,
7026
+ style
7027
+ }, ref) => {
7028
+ const [isHovered, setIsHovered] = React41.useState(false);
7029
+ const [isStarHovered, setIsStarHovered] = React41.useState(false);
7030
+ const basePadding = 24;
7031
+ const tierIndent = (tier - 1) * 12;
7032
+ const chevronSpace = hasChildren ? 20 : 0;
7033
+ const leftPadding = basePadding + tierIndent - chevronSpace;
7034
+ const getTextColor = () => {
7035
+ if (active) return "#005700";
7036
+ if (isHovered) return "#2f2f2f";
7037
+ return "#333333";
7038
+ };
7039
+ const getBackgroundColor = () => {
7040
+ if (active) return "#f0faf3";
7041
+ if (isHovered) return "#f8f8f8";
7042
+ return "transparent";
7043
+ };
7044
+ const getFontWeight = () => {
7045
+ return active ? 600 : 400;
7046
+ };
7047
+ const showStar = isHovered || active;
7048
+ const getStarColor = () => {
7049
+ if (favourited) return "#0e8a0e";
7050
+ if (isStarHovered) return "#2f2f2f";
7051
+ return "#0e8a0e";
7052
+ };
7053
+ const containerStyles6 = {
7054
+ display: "flex",
7055
+ alignItems: "center",
7056
+ gap: "8px",
7057
+ width: "168px",
7058
+ paddingTop: "8px",
7059
+ paddingBottom: "8px",
7060
+ paddingLeft: `${leftPadding}px`,
7061
+ paddingRight: "8px",
7062
+ borderRadius: "99px",
7063
+ backgroundColor: getBackgroundColor(),
7064
+ boxShadow: focused ? "0px 0px 0px 3px #3cad51" : "none",
7065
+ cursor: "pointer",
7066
+ boxSizing: "border-box",
7067
+ transition: "background-color 150ms ease",
7068
+ outline: "none",
7069
+ ...style
7070
+ };
7071
+ const chevronStyles = {
7072
+ display: "flex",
7073
+ alignItems: "center",
7074
+ justifyContent: "center",
7075
+ flexShrink: 0,
7076
+ width: "16px",
7077
+ height: "16px",
7078
+ marginLeft: "-4px"
7079
+ };
7080
+ const labelStyles10 = {
7081
+ flex: 1,
7082
+ fontFamily: "'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
7083
+ fontSize: "13px",
7084
+ fontWeight: getFontWeight(),
7085
+ color: getTextColor(),
7086
+ lineHeight: 1.5,
7087
+ overflow: "hidden",
7088
+ textOverflow: "ellipsis",
7089
+ whiteSpace: "nowrap"
7090
+ };
7091
+ const starContainerStyles = {
7092
+ display: "flex",
7093
+ alignItems: "center",
7094
+ justifyContent: "center",
7095
+ flexShrink: 0,
7096
+ width: "16px",
7097
+ height: "16px",
7098
+ opacity: showStar ? 1 : 0,
7099
+ transition: "opacity 150ms ease"
7100
+ };
7101
+ const handleClick = () => {
7102
+ onClick?.();
7103
+ };
7104
+ const handleChevronClick = (e) => {
7105
+ e.stopPropagation();
7106
+ onExpandClick?.();
7107
+ };
7108
+ const handleStarClick = (e) => {
7109
+ e.stopPropagation();
7110
+ onFavouriteClick?.();
7111
+ };
7112
+ const handleKeyDown = (e) => {
7113
+ if (e.key === "Enter" || e.key === " ") {
7114
+ e.preventDefault();
7115
+ onClick?.();
7116
+ }
7117
+ };
7118
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
7119
+ "div",
7120
+ {
7121
+ ref,
7122
+ className,
7123
+ style: containerStyles6,
7124
+ onClick: handleClick,
7125
+ onMouseEnter: () => setIsHovered(true),
7126
+ onMouseLeave: () => {
7127
+ setIsHovered(false);
7128
+ setIsStarHovered(false);
7129
+ },
7130
+ onKeyDown: handleKeyDown,
7131
+ tabIndex: 0,
7132
+ role: "button",
7133
+ "aria-expanded": hasChildren ? expanded : void 0,
7134
+ "aria-label": label,
7135
+ children: [
7136
+ hasChildren && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
7137
+ "div",
7138
+ {
7139
+ style: chevronStyles,
7140
+ onClick: handleChevronClick,
7141
+ role: "button",
7142
+ "aria-label": expanded ? "Collapse" : "Expand",
7143
+ children: expanded ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_lucide_react18.ChevronDown, { size: 14, color: "#7e7e7e", strokeWidth: 2 }) : /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_lucide_react18.ChevronRight, { size: 14, color: "#7e7e7e", strokeWidth: 2 })
7144
+ }
7145
+ ),
7146
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { style: labelStyles10, children: label }),
7147
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
7148
+ "div",
7149
+ {
7150
+ style: starContainerStyles,
7151
+ onClick: handleStarClick,
7152
+ onMouseEnter: () => setIsStarHovered(true),
7153
+ onMouseLeave: () => setIsStarHovered(false),
7154
+ role: "button",
7155
+ "aria-label": favourited ? "Remove from favourites" : "Add to favourites",
7156
+ "aria-pressed": favourited,
7157
+ children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
7158
+ import_lucide_react18.Star,
7159
+ {
7160
+ size: 15,
7161
+ color: getStarColor(),
7162
+ fill: favourited ? "#0e8a0e" : "none",
7163
+ strokeWidth: 2
7164
+ }
7165
+ )
7166
+ }
7167
+ )
7168
+ ]
7169
+ }
7170
+ );
7171
+ }
7172
+ );
7173
+ SideNavItem.displayName = "SideNavItem";
6752
7174
  // Annotate the CommonJS export names for ESM import in node:
6753
7175
  0 && (module.exports = {
6754
7176
  Avatar,
@@ -6778,6 +7200,9 @@ TopNavBar.displayName = "TopNavBar";
6778
7200
  SectionHeading,
6779
7201
  SectionHeadingInteractive,
6780
7202
  SectionIcon,
7203
+ SideNavBar,
7204
+ SideNavButton,
7205
+ SideNavItem,
6781
7206
  SubSectionHeading,
6782
7207
  SubSectionInteractive,
6783
7208
  Table,