pixelize-design-library 2.4.2-beta.57 → 2.4.2-beta.59

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/CHANGELOG.md +86 -0
  2. package/COMPONENT-GOTCHAS.md +88 -2
  3. package/DESIGN-GUIDE.md +27 -4
  4. package/dist/Components/AppSwitcher/AppSwitcher.js +5 -1
  5. package/dist/Components/AppSwitcher/AppSwitcherProps.d.ts +2 -0
  6. package/dist/Components/AppSwitcher/AppSwitcherProps.js +7 -4
  7. package/dist/Components/Breadcrumbs/Breadcrumbs.d.ts +1 -1
  8. package/dist/Components/Breadcrumbs/Breadcrumbs.js +33 -10
  9. package/dist/Components/Breadcrumbs/BreadcrumbsProps.d.ts +16 -2
  10. package/dist/Components/Card/Card.d.ts +3 -1
  11. package/dist/Components/Card/Card.js +12 -2
  12. package/dist/Components/Card/CardProps.d.ts +5 -1
  13. package/dist/Components/Commerce/commerceTypes.d.ts +5 -0
  14. package/dist/Components/Editor/Editor.js +50 -2
  15. package/dist/Components/Editor/EditorFieldBar.d.ts +15 -0
  16. package/dist/Components/Editor/EditorFieldBar.js +19 -0
  17. package/dist/Components/Editor/EditorProps.d.ts +74 -1
  18. package/dist/Components/Editor/MakeDynamicDialog.d.ts +12 -0
  19. package/dist/Components/Editor/MakeDynamicDialog.js +59 -0
  20. package/dist/Components/Editor/editorLabels.d.ts +4 -0
  21. package/dist/Components/Editor/editorLabels.js +24 -0
  22. package/dist/Components/Editor/editorTokenStyles.d.ts +28 -0
  23. package/dist/Components/Editor/editorTokenStyles.js +30 -0
  24. package/dist/Components/Editor/editorTokens.d.ts +26 -0
  25. package/dist/Components/Editor/editorTokens.js +134 -0
  26. package/dist/Components/Editor/useEditorBridge.d.ts +40 -0
  27. package/dist/Components/Editor/useEditorBridge.js +141 -0
  28. package/dist/Components/Kbd/Kbd.d.ts +6 -0
  29. package/dist/Components/Kbd/Kbd.js +33 -0
  30. package/dist/Components/Kbd/KbdProps.d.ts +17 -0
  31. package/dist/Components/Kbd/KbdProps.js +2 -0
  32. package/dist/Components/LauncherTrigger/LauncherTrigger.d.ts +4 -0
  33. package/dist/Components/LauncherTrigger/LauncherTrigger.js +41 -0
  34. package/dist/Components/LauncherTrigger/LauncherTriggerProps.d.ts +16 -0
  35. package/dist/Components/LauncherTrigger/LauncherTriggerProps.js +2 -0
  36. package/dist/Components/MediaGallery/MediaGallery.js +1 -1
  37. package/dist/Components/NavLauncher/NavLauncher.d.ts +3 -0
  38. package/dist/Components/NavLauncher/NavLauncher.js +395 -0
  39. package/dist/Components/NavLauncher/NavLauncherProps.d.ts +187 -0
  40. package/dist/Components/NavLauncher/NavLauncherProps.js +2 -0
  41. package/dist/Components/NavLauncher/NewTabLink.d.ts +3 -0
  42. package/dist/Components/NavLauncher/NewTabLink.js +14 -0
  43. package/dist/Components/NavLauncher/PinToggle.d.ts +3 -0
  44. package/dist/Components/NavLauncher/PinToggle.js +21 -0
  45. package/dist/Components/NavLauncher/launcherParts.d.ts +93 -0
  46. package/dist/Components/NavLauncher/launcherParts.js +130 -0
  47. package/dist/Components/NavLauncher/match.d.ts +53 -0
  48. package/dist/Components/NavLauncher/match.js +178 -0
  49. package/dist/Components/NavLauncher/revealStyles.d.ts +4 -0
  50. package/dist/Components/NavLauncher/revealStyles.js +19 -0
  51. package/dist/Components/NavigationBar/NavigationBar.d.ts +1 -1
  52. package/dist/Components/NavigationBar/NavigationBar.js +2 -2
  53. package/dist/Components/NavigationBar/NavigationBarProps.d.ts +2 -0
  54. package/dist/Components/PageHeader/PageHeader.d.ts +1 -1
  55. package/dist/Components/PageHeader/PageHeader.js +9 -2
  56. package/dist/Components/PageHeader/PageHeaderProps.d.ts +8 -0
  57. package/dist/Components/PdfViewer/PdfViewer.d.ts +21 -4
  58. package/dist/Components/PdfViewer/PdfViewer.js +124 -3
  59. package/dist/Components/ProductCard/ProductCard.js +8 -3
  60. package/dist/Components/ProductCard/ProductCardMedia.js +3 -3
  61. package/dist/Components/ProductCard/QuickAddSheet.js +2 -2
  62. package/dist/Components/ProductCard/cardMetrics.d.ts +1 -0
  63. package/dist/Components/ProductCard/cardMetrics.js +3 -2
  64. package/dist/Components/ProductDetails/ProductDetails.d.ts +1 -1
  65. package/dist/Components/ProductDetails/ProductDetails.js +6 -5
  66. package/dist/Components/ProductDetails/ProductDetailsProps.d.ts +2 -0
  67. package/dist/Components/Search/Search.js +2 -1
  68. package/dist/Components/SideBar/SecondaryBar.js +4 -3
  69. package/dist/Components/SideBar/SideBar.d.ts +1 -1
  70. package/dist/Components/SideBar/SideBar.js +30 -9
  71. package/dist/Components/SideBar/SideBarProps.d.ts +32 -0
  72. package/dist/Components/SideBar/components/MenuItemBox.d.ts +6 -0
  73. package/dist/Components/SideBar/components/MenuItemBox.js +8 -4
  74. package/dist/Components/SideBar/components/MenuPopoverContent.js +3 -2
  75. package/dist/Components/SideBar/components/OtherApps.js +2 -1
  76. package/dist/Components/SideBar/components/PinnedSection.d.ts +17 -0
  77. package/dist/Components/SideBar/components/PinnedSection.js +98 -0
  78. package/dist/Components/SideBar/sidebarFocus.d.ts +23 -0
  79. package/dist/Components/SideBar/sidebarFocus.js +20 -0
  80. package/dist/Components/StageProgress/StageProgress.js +2 -2
  81. package/dist/Components/StageProgress/StageProgressProps.d.ts +2 -0
  82. package/dist/Components/StageProgress/StepperStage.js +5 -2
  83. package/dist/Components/WizardDialog/WizardDialog.d.ts +9 -0
  84. package/dist/Components/WizardDialog/WizardDialog.js +102 -0
  85. package/dist/Components/WizardDialog/WizardDialogProps.d.ts +48 -0
  86. package/dist/Components/WizardDialog/WizardDialogProps.js +2 -0
  87. package/dist/Components/WizardDialog/useWizardFlow.d.ts +22 -0
  88. package/dist/Components/WizardDialog/useWizardFlow.js +47 -0
  89. package/dist/Components/WizardDialog/wizardSteps.d.ts +31 -0
  90. package/dist/Components/WizardDialog/wizardSteps.js +40 -0
  91. package/dist/Hooks/useMatchMedia.d.ts +2 -0
  92. package/dist/Hooks/useMatchMedia.js +36 -0
  93. package/dist/Theme/chakra/motion.js +2 -16
  94. package/dist/Utils/price.js +11 -6
  95. package/dist/esm/Components/AppSwitcher/AppSwitcher.js +2 -1
  96. package/dist/esm/Components/AppSwitcher/AppSwitcherProps.js +5 -3
  97. package/dist/esm/Components/Breadcrumbs/Breadcrumbs.js +35 -12
  98. package/dist/esm/Components/Card/Card.js +12 -2
  99. package/dist/esm/Components/Editor/Editor.js +48 -3
  100. package/dist/esm/Components/Editor/EditorFieldBar.js +13 -0
  101. package/dist/esm/Components/Editor/MakeDynamicDialog.js +20 -0
  102. package/dist/esm/Components/Editor/editorLabels.js +20 -0
  103. package/dist/esm/Components/Editor/editorTokenStyles.js +25 -0
  104. package/dist/esm/Components/Editor/editorTokens.js +121 -0
  105. package/dist/esm/Components/Editor/useEditorBridge.js +138 -0
  106. package/dist/esm/Components/Kbd/Kbd.js +28 -0
  107. package/dist/esm/Components/Kbd/KbdProps.js +1 -0
  108. package/dist/esm/Components/LauncherTrigger/LauncherTrigger.js +37 -0
  109. package/dist/esm/Components/LauncherTrigger/LauncherTriggerProps.js +1 -0
  110. package/dist/esm/Components/MediaGallery/MediaGallery.js +1 -1
  111. package/dist/esm/Components/NavLauncher/NavLauncher.js +356 -0
  112. package/dist/esm/Components/NavLauncher/NavLauncherProps.js +1 -0
  113. package/dist/esm/Components/NavLauncher/NewTabLink.js +11 -0
  114. package/dist/esm/Components/NavLauncher/PinToggle.js +18 -0
  115. package/dist/esm/Components/NavLauncher/launcherParts.js +110 -0
  116. package/dist/esm/Components/NavLauncher/match.js +172 -0
  117. package/dist/esm/Components/NavLauncher/revealStyles.js +15 -0
  118. package/dist/esm/Components/NavigationBar/NavigationBar.js +3 -3
  119. package/dist/esm/Components/PageHeader/PageHeader.js +9 -2
  120. package/dist/esm/Components/PdfViewer/PdfViewer.js +123 -2
  121. package/dist/esm/Components/ProductCard/ProductCard.js +9 -4
  122. package/dist/esm/Components/ProductCard/ProductCardMedia.js +3 -3
  123. package/dist/esm/Components/ProductCard/QuickAddSheet.js +2 -2
  124. package/dist/esm/Components/ProductCard/cardMetrics.js +2 -1
  125. package/dist/esm/Components/ProductDetails/ProductDetails.js +6 -5
  126. package/dist/esm/Components/Search/Search.js +3 -2
  127. package/dist/esm/Components/SideBar/SecondaryBar.js +4 -3
  128. package/dist/esm/Components/SideBar/SideBar.js +31 -10
  129. package/dist/esm/Components/SideBar/components/MenuItemBox.js +4 -2
  130. package/dist/esm/Components/SideBar/components/MenuPopoverContent.js +3 -2
  131. package/dist/esm/Components/SideBar/components/OtherApps.js +2 -1
  132. package/dist/esm/Components/SideBar/components/PinnedSection.js +92 -0
  133. package/dist/esm/Components/SideBar/sidebarFocus.js +15 -0
  134. package/dist/esm/Components/StageProgress/StageProgress.js +2 -2
  135. package/dist/esm/Components/StageProgress/StepperStage.js +5 -2
  136. package/dist/esm/Components/WizardDialog/WizardDialog.js +58 -0
  137. package/dist/esm/Components/WizardDialog/WizardDialogProps.js +1 -0
  138. package/dist/esm/Components/WizardDialog/useWizardFlow.js +44 -0
  139. package/dist/esm/Components/WizardDialog/wizardSteps.js +35 -0
  140. package/dist/esm/Hooks/useMatchMedia.js +32 -0
  141. package/dist/esm/Theme/chakra/motion.js +2 -16
  142. package/dist/esm/Utils/price.js +11 -6
  143. package/dist/esm/index.js +7 -0
  144. package/dist/index.d.ts +19 -4
  145. package/dist/index.js +21 -1
  146. package/package.json +1 -1
  147. package/dist/Components/MediaGallery/useMatchMedia.d.ts +0 -2
  148. package/dist/Components/MediaGallery/useMatchMedia.js +0 -20
  149. package/dist/Components/ProductCard/useMinWidth.d.ts +0 -2
  150. package/dist/Components/ProductCard/useMinWidth.js +0 -20
  151. package/dist/esm/Components/MediaGallery/useMatchMedia.js +0 -16
  152. package/dist/esm/Components/ProductCard/useMinWidth.js +0 -16
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = PinToggle;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("@chakra-ui/react");
6
+ const motion_1 = require("../../Theme/tokens/primitives/motion");
7
+ const useCustomTheme_1 = require("../../Theme/useCustomTheme");
8
+ const revealStyles_1 = require("./revealStyles");
9
+ const STAR = "M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01z";
10
+ function Star({ filled, size }) {
11
+ return ((0, jsx_runtime_1.jsx)("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: filled ? "currentColor" : "none", stroke: "currentColor", strokeWidth: 1.7, strokeLinejoin: "round", "aria-hidden": true, children: (0, jsx_runtime_1.jsx)("path", { d: STAR }) }));
12
+ }
13
+ /** Star toggle: outline when unpinned, filled in the accent when pinned; appears on row hover or focus and never follows the row link. */
14
+ function PinToggle({ isPinned, label, onToggle, title, size = 13, tabIndex }) {
15
+ const { colors } = (0, useCustomTheme_1.useCustomTheme)();
16
+ return ((0, jsx_runtime_1.jsx)(react_1.IconButton, { "aria-label": label, "aria-pressed": isPinned, title: title !== null && title !== void 0 ? title : label, icon: (0, jsx_runtime_1.jsx)(Star, { filled: isPinned, size: size }), variant: "ghost", minW: "22px", w: "22px", h: "22px", borderRadius: "md", tabIndex: tabIndex, color: isPinned ? colors.accentText : colors.textMuted, opacity: 0, transition: (0, motion_1.transitionFor)(["opacity", "background-color"]), sx: (0, revealStyles_1.revealStyles)(colors), onClick: (event) => {
17
+ event.preventDefault();
18
+ event.stopPropagation();
19
+ onToggle();
20
+ } }));
21
+ }
@@ -0,0 +1,93 @@
1
+ import { type ElementType, type KeyboardEvent, type MouseEvent, type ReactNode } from "react";
2
+ import type { AppOption } from "../AppSwitcher/AppSwitcherProps";
3
+ import type { LauncherLabels, LauncherModule, LauncherScreen } from "./NavLauncherProps";
4
+ export declare const ITEM_SELECTOR = "[data-launcher-item]";
5
+ export declare const isPlainClick: (event: MouseEvent) => boolean;
6
+ export type LinkCtx = {
7
+ linkAs: ElementType;
8
+ onPlainClick: (event: MouseEvent) => void;
9
+ };
10
+ export declare const useRowHover: () => {
11
+ bg: string;
12
+ _hover: {
13
+ bg: string;
14
+ };
15
+ _focusWithin: {
16
+ bg: string;
17
+ };
18
+ };
19
+ type BadgeProps = {
20
+ value?: number | string;
21
+ size?: "row" | "tile";
22
+ };
23
+ export declare function CountBadge({ value, size }: BadgeProps): import("react/jsx-runtime").JSX.Element | null;
24
+ export declare function NewTag({ label }: {
25
+ label: string;
26
+ }): import("react/jsx-runtime").JSX.Element;
27
+ type SectionHeaderProps = {
28
+ label: string;
29
+ meta?: string;
30
+ isDecorative?: boolean;
31
+ isRail?: boolean;
32
+ hasCount?: boolean;
33
+ };
34
+ export declare function SectionHeader({ label, meta, isDecorative, isRail, hasCount, }: SectionHeaderProps): import("react/jsx-runtime").JSX.Element;
35
+ type RowIconProps = {
36
+ icon?: ElementType;
37
+ size: number;
38
+ stroke?: number;
39
+ mt?: string;
40
+ };
41
+ export declare function RowIcon({ icon: Icon, size, stroke, mt }: RowIconProps): import("react/jsx-runtime").JSX.Element | null;
42
+ export declare function Highlight({ text, query }: {
43
+ text: string;
44
+ query: string;
45
+ }): import("react/jsx-runtime").JSX.Element;
46
+ export declare function RowActions({ children }: {
47
+ children: ReactNode;
48
+ }): import("react/jsx-runtime").JSX.Element;
49
+ export declare function RowTip({ text }: {
50
+ text: string;
51
+ }): import("react/jsx-runtime").JSX.Element;
52
+ type ModuleRowProps = {
53
+ module: LauncherModule;
54
+ keyScreens: LauncherScreen[];
55
+ isPinned: boolean;
56
+ onTogglePin?: () => void;
57
+ pinId: string;
58
+ labels: LauncherLabels;
59
+ link: LinkCtx;
60
+ };
61
+ export declare function ModuleRow({ module, keyScreens, isPinned, onTogglePin, pinId, labels, link, }: ModuleRowProps): import("react/jsx-runtime").JSX.Element;
62
+ type RailRowProps = {
63
+ screen: LauncherScreen;
64
+ module: LauncherModule;
65
+ link: LinkCtx;
66
+ isStrong?: boolean;
67
+ trailing?: ReactNode;
68
+ pinId?: string;
69
+ };
70
+ export declare function RailRow({ screen, module, link, isStrong, trailing, pinId, }: RailRowProps): import("react/jsx-runtime").JSX.Element;
71
+ type PinTextButtonProps = {
72
+ label: string;
73
+ text: string;
74
+ onToggle: () => void;
75
+ };
76
+ export declare function PinTextButton({ label, text, onToggle }: PinTextButtonProps): import("react/jsx-runtime").JSX.Element;
77
+ type PinnedTileProps = {
78
+ screen: LauncherScreen;
79
+ module: LauncherModule;
80
+ link: LinkCtx;
81
+ labels: LauncherLabels;
82
+ onTogglePin?: () => void;
83
+ };
84
+ export declare function PinnedTile({ screen, module, link, labels, onTogglePin, }: PinnedTileProps): import("react/jsx-runtime").JSX.Element;
85
+ type AppsSectionProps = {
86
+ apps: readonly AppOption[];
87
+ hues: readonly string[];
88
+ currentAppId?: string;
89
+ heading: string;
90
+ onSelect: (app: AppOption, event: MouseEvent | KeyboardEvent) => void;
91
+ };
92
+ export declare function AppsSection({ apps, hues, currentAppId, heading, onSelect, }: AppsSectionProps): import("react/jsx-runtime").JSX.Element;
93
+ export {};
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.useRowHover = exports.isPlainClick = exports.ITEM_SELECTOR = void 0;
7
+ exports.CountBadge = CountBadge;
8
+ exports.NewTag = NewTag;
9
+ exports.SectionHeader = SectionHeader;
10
+ exports.RowIcon = RowIcon;
11
+ exports.Highlight = Highlight;
12
+ exports.RowActions = RowActions;
13
+ exports.RowTip = RowTip;
14
+ exports.ModuleRow = ModuleRow;
15
+ exports.RailRow = RailRow;
16
+ exports.PinTextButton = PinTextButton;
17
+ exports.PinnedTile = PinnedTile;
18
+ exports.AppsSection = AppsSection;
19
+ const jsx_runtime_1 = require("react/jsx-runtime");
20
+ const react_1 = require("@chakra-ui/react");
21
+ const lucide_react_1 = require("lucide-react");
22
+ const react_2 = require("react");
23
+ const focusRing_styles_1 = require("../../Theme/chakra/focusRing.styles");
24
+ const filledSurface_1 = require("../../Theme/tokens/builders/filledSurface");
25
+ const rowStates_1 = require("../../Theme/tokens/builders/rowStates");
26
+ const motion_1 = require("../../Theme/tokens/primitives/motion");
27
+ const useCustomTheme_1 = require("../../Theme/useCustomTheme");
28
+ const AppMark_1 = __importDefault(require("../AppSwitcher/AppMark"));
29
+ const match_1 = require("./match");
30
+ const NewTabLink_1 = __importDefault(require("./NewTabLink"));
31
+ const PinToggle_1 = __importDefault(require("./PinToggle"));
32
+ const revealStyles_1 = require("./revealStyles");
33
+ exports.ITEM_SELECTOR = "[data-launcher-item]";
34
+ const isPlainClick = (event) => event.button === 0 &&
35
+ !event.metaKey &&
36
+ !event.ctrlKey &&
37
+ !event.shiftKey &&
38
+ !event.altKey;
39
+ exports.isPlainClick = isPlainClick;
40
+ const useRowHover = () => {
41
+ const { colors } = (0, useCustomTheme_1.useCustomTheme)();
42
+ const hover = (0, rowStates_1.listRowBackgrounds)(colors).active;
43
+ return { bg: hover, _hover: { bg: hover }, _focusWithin: { bg: hover } };
44
+ };
45
+ exports.useRowHover = useRowHover;
46
+ function CountBadge({ value, size = "row" }) {
47
+ const { colors } = (0, useCustomTheme_1.useCustomTheme)();
48
+ if (value === undefined || value === 0 || value === "")
49
+ return null;
50
+ const fill = (0, filledSurface_1.resolveFilledSurface)(colors.primary, colors);
51
+ const isRow = size === "row";
52
+ return ((0, jsx_runtime_1.jsx)(react_1.Box, { as: "span", flexShrink: 0, minW: isRow ? "20px" : undefined, h: isRow ? "18px" : "17px", px: "6px", mr: isRow ? "2px" : 0, borderRadius: "full", bg: fill.fill, color: fill.color, fontSize: isRow ? "10.5px" : "10px", fontWeight: 700, display: "inline-flex", alignItems: "center", justifyContent: "center", sx: { fontVariantNumeric: "tabular-nums" }, children: value }));
53
+ }
54
+ function NewTag({ label }) {
55
+ const { colors } = (0, useCustomTheme_1.useCustomTheme)();
56
+ return ((0, jsx_runtime_1.jsx)(react_1.Box, { as: "span", flexShrink: 0, fontSize: "10px", fontWeight: 600, letterSpacing: "0.02em", color: colors.accentText, opacity: 0.85, children: label }));
57
+ }
58
+ function SectionHeader({ label, meta, isDecorative = false, isRail = false, hasCount = true, }) {
59
+ const { colors } = (0, useCustomTheme_1.useCustomTheme)();
60
+ return ((0, jsx_runtime_1.jsxs)(react_1.Flex, { align: "baseline", gap: "6px", px: isRail ? "4px" : "8px", pb: "5px", mb: hasCount ? 0 : "2px", borderBottomWidth: "1px", borderColor: colors.boxborder[200], "aria-hidden": isDecorative || undefined, children: [(0, jsx_runtime_1.jsx)(react_1.Heading, { as: isDecorative ? "div" : "h2", m: 0, fontSize: "12.5px", fontWeight: 600, letterSpacing: "-0.003em", color: colors.text[900], children: label }), meta ? ((0, jsx_runtime_1.jsx)(react_1.Text, { as: "span", fontSize: "11.5px", color: colors.textMuted, sx: { fontVariantNumeric: "tabular-nums" }, children: meta })) : null] }));
61
+ }
62
+ function RowIcon({ icon: Icon, size, stroke = 1.75, mt }) {
63
+ const { colors } = (0, useCustomTheme_1.useCustomTheme)();
64
+ if (!Icon)
65
+ return null;
66
+ return ((0, jsx_runtime_1.jsx)(react_1.Box, { as: "span", color: colors.textMuted, display: "inline-flex", flexShrink: 0, mt: mt, transition: (0, motion_1.transitionFor)(["color"]), _groupHover: { color: colors.accentText }, _groupFocusWithin: { color: colors.accentText }, sx: { "[data-reveal=true] &": { color: colors.accentText } }, children: (0, jsx_runtime_1.jsx)(Icon, { size: size, strokeWidth: stroke, "aria-hidden": true }) }));
67
+ }
68
+ function Highlight({ text, query }) {
69
+ const { colors } = (0, useCustomTheme_1.useCustomTheme)();
70
+ return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, match_1.highlightSegments)(text, query).map((segment, i) => segment.isMatch ? ((0, jsx_runtime_1.jsx)(react_1.Box, { as: "mark", bg: colors.primary.opacity[24], color: "inherit", borderRadius: "3px", px: "1px", children: segment.text }, i)) : ((0, jsx_runtime_1.jsx)(react_2.Fragment, { children: segment.text }, i))) }));
71
+ }
72
+ function RowActions({ children }) {
73
+ return ((0, jsx_runtime_1.jsx)(react_1.Flex, { position: "absolute", top: "7px", right: "4px", h: "19px", align: "center", gap: "2px", zIndex: 1, children: children }));
74
+ }
75
+ function RowTip({ text }) {
76
+ const { colors } = (0, useCustomTheme_1.useCustomTheme)();
77
+ return ((0, jsx_runtime_1.jsx)(react_1.Box, { role: "tooltip", position: "absolute", right: "20px", top: "-26px", zIndex: 2, px: "8px", py: "3px", borderRadius: "6px", fontSize: "11px", fontWeight: 600, whiteSpace: "nowrap", bg: colors.text[900], color: colors.surfaceRaised, visibility: "hidden", pointerEvents: "none", _groupHover: { visibility: "visible" }, children: text }));
78
+ }
79
+ function ModuleRow({ module, keyScreens, isPinned, onTogglePin, pinId, labels, link, }) {
80
+ const { colors } = (0, useCustomTheme_1.useCustomTheme)();
81
+ const hover = (0, exports.useRowHover)();
82
+ const ring = (0, focusRing_styles_1.focusVisibleStyles)(colors);
83
+ const base = typeof module.badge === "number" || module.badge ? 24 : 0;
84
+ const open = base + (onTogglePin ? 46 : 24);
85
+ return ((0, jsx_runtime_1.jsxs)(react_1.Flex, { "data-group": true, "data-nav-cell": true, position: "relative", align: "flex-start", gap: "10px", minH: "34px", pl: "8px", pr: "4px", pt: "7px", pb: "5px", borderRadius: "8px", transition: (0, motion_1.transitionFor)(["background-color"]), _hover: hover._hover, _focusWithin: hover._focusWithin, children: [(0, jsx_runtime_1.jsx)(RowIcon, { icon: module.icon, size: 16, mt: "2px" }), (0, jsx_runtime_1.jsxs)(react_1.Flex, { direction: "column", flex: 1, minW: 0, children: [(0, jsx_runtime_1.jsxs)(react_1.Flex, { align: "center", gap: "6px", h: "19px", minW: 0, pr: `${base}px`, _groupHover: { pr: `${open}px` }, _groupFocusWithin: { pr: `${open}px` }, children: [(0, jsx_runtime_1.jsx)(react_1.Box, { as: link.linkAs, href: module.href, "data-launcher-item": true, "data-pin-id": onTogglePin ? pinId : undefined, title: module.label, onClick: link.onPlainClick, minW: 0, fontSize: "13.5px", fontWeight: 500, color: colors.text[900], noOfLines: 1, borderRadius: "sm", sx: ring, children: module.label }), module.isNew ? (0, jsx_runtime_1.jsx)(NewTag, { label: labels.newBadge }) : null] }), keyScreens.length ? ((0, jsx_runtime_1.jsx)(react_1.Box, { role: "group", "aria-label": `${module.label} ${labels.screens}`, fontSize: "11.5px", lineHeight: "15px", color: colors.textMuted, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", children: keyScreens.map((screen, i) => ((0, jsx_runtime_1.jsxs)(react_2.Fragment, { children: [i > 0 ? ((0, jsx_runtime_1.jsx)(react_1.Box, { as: "span", "aria-hidden": true, mx: "5px", opacity: 0.7, children: "\u00B7" })) : null, (0, jsx_runtime_1.jsx)(react_1.Box, { as: link.linkAs, href: screen.href, "data-launcher-item": true, title: `${screen.label} — ${module.label}`, onClick: link.onPlainClick, color: "inherit", borderRadius: "sm", _hover: {
86
+ textDecoration: "underline",
87
+ textUnderlineOffset: "2px",
88
+ }, sx: ring, children: screen.label })] }, screen.id))) })) : null] }), (0, jsx_runtime_1.jsxs)(RowActions, { children: [(0, jsx_runtime_1.jsx)(CountBadge, { value: module.badge }), onTogglePin ? ((0, jsx_runtime_1.jsx)(PinToggle_1.default, { isPinned: isPinned, label: isPinned ? labels.unpin(module.label) : labels.pin(module.label), title: "", onToggle: onTogglePin })) : null, (0, jsx_runtime_1.jsx)(NewTabLink_1.default, { href: module.href, label: labels.openInNewTab(module.label), linkAs: link.linkAs })] }), onTogglePin ? ((0, jsx_runtime_1.jsx)(RowTip, { text: isPinned ? labels.unpinTip : labels.pinTip })) : null] }));
89
+ }
90
+ function RailRow({ screen, module, link, isStrong = false, trailing, pinId, }) {
91
+ var _a;
92
+ const { colors } = (0, useCustomTheme_1.useCustomTheme)();
93
+ const hover = (0, exports.useRowHover)();
94
+ return ((0, jsx_runtime_1.jsxs)(react_1.Flex, { "data-group": true, align: "center", gap: "10px", h: "32px", pl: "8px", pr: "4px", borderRadius: "8px", transition: (0, motion_1.transitionFor)(["background-color"]), _hover: hover._hover, _focusWithin: hover._focusWithin, children: [(0, jsx_runtime_1.jsx)(RowIcon, { icon: (_a = screen.icon) !== null && _a !== void 0 ? _a : module.icon, size: 15 }), (0, jsx_runtime_1.jsx)(react_1.Box, { as: link.linkAs, href: screen.href, "data-launcher-item": true, "data-pin-id": pinId, onClick: link.onPlainClick, flex: 1, minW: 0, fontSize: "13px", fontWeight: isStrong ? 500 : 400, color: colors.text[900], noOfLines: 1, borderRadius: "sm", sx: (0, focusRing_styles_1.focusVisibleStyles)(colors), children: screen.label }), trailing] }));
95
+ }
96
+ function PinTextButton({ label, text, onToggle }) {
97
+ const { colors } = (0, useCustomTheme_1.useCustomTheme)();
98
+ return ((0, jsx_runtime_1.jsxs)(react_1.Box, { as: "button", type: "button", "aria-label": label, flexShrink: 0, h: "22px", px: "7px", display: "inline-flex", alignItems: "center", gap: "4px", borderRadius: "6px", borderWidth: "1px", borderColor: colors.boxborder[200], bg: colors.surfaceRaised, color: colors.text[700], fontSize: "11px", fontWeight: 600, cursor: "pointer", opacity: 0, transition: (0, motion_1.transitionFor)(["opacity", "background-color"]), sx: { ...(0, revealStyles_1.revealStyles)(colors), "@media (hover: none)": { opacity: 1 } }, onClick: (event) => {
99
+ event.preventDefault();
100
+ event.stopPropagation();
101
+ onToggle();
102
+ }, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Star, { size: 11, strokeWidth: 2, "aria-hidden": true }), text] }));
103
+ }
104
+ function PinnedTile({ screen, module, link, labels, onTogglePin, }) {
105
+ var _a;
106
+ const { colors } = (0, useCustomTheme_1.useCustomTheme)();
107
+ const Icon = (_a = screen.icon) !== null && _a !== void 0 ? _a : module.icon;
108
+ return ((0, jsx_runtime_1.jsxs)(react_1.Flex, { "data-group": true, align: "center", gap: "8px", h: "36px", pl: "9px", pr: "4px", borderRadius: "9px", borderWidth: "1px", borderColor: colors.boxborder[200], bg: colors.surfaceRaised, title: screen.label, transition: (0, motion_1.transitionFor)(["border-color"]), _hover: { borderColor: colors.gray[300] }, children: [Icon ? ((0, jsx_runtime_1.jsx)(react_1.Box, { as: "span", display: "inline-flex", flexShrink: 0, color: colors.accentText, children: (0, jsx_runtime_1.jsx)(Icon, { size: 15, strokeWidth: 1.8, "aria-hidden": true }) })) : null, (0, jsx_runtime_1.jsx)(react_1.Box, { as: link.linkAs, href: screen.href, "data-launcher-item": true, "data-pin-id": onTogglePin ? screen.id : undefined, onClick: link.onPlainClick, flex: 1, minW: 0, fontSize: "13px", fontWeight: 500, color: colors.text[900], noOfLines: 1, borderRadius: "sm", sx: (0, focusRing_styles_1.focusVisibleStyles)(colors), children: screen.label }), (0, jsx_runtime_1.jsx)(CountBadge, { value: screen.badge, size: "tile" }), onTogglePin ? ((0, jsx_runtime_1.jsx)(react_1.Box, { flexShrink: 0, w: "0", overflow: "hidden", transition: (0, motion_1.transitionFor)(["width"]), _groupHover: { w: "22px" }, _groupFocusWithin: { w: "22px" }, children: (0, jsx_runtime_1.jsx)(PinToggle_1.default, { isPinned: true, size: 12, label: labels.unpin(screen.label), title: labels.unpinTip, onToggle: onTogglePin }) })) : null] }));
109
+ }
110
+ function AppsSection({ apps, hues, currentAppId, heading, onSelect, }) {
111
+ const { colors } = (0, useCustomTheme_1.useCustomTheme)();
112
+ const rows = (0, rowStates_1.listRowBackgrounds)(colors);
113
+ const ring = (0, focusRing_styles_1.focusVisibleStyles)(colors);
114
+ return ((0, jsx_runtime_1.jsxs)(react_1.Box, { children: [(0, jsx_runtime_1.jsx)(SectionHeader, { label: heading, isRail: true, hasCount: false }), (0, jsx_runtime_1.jsx)(react_1.Box, { as: "ul", listStyleType: "none", m: 0, p: 0, "aria-label": heading, children: apps.map((app, index) => {
115
+ var _a;
116
+ const isCurrent = app.id === currentAppId;
117
+ const interactive = !isCurrent && !app.locked;
118
+ return ((0, jsx_runtime_1.jsx)(react_1.Box, { as: "li", children: (0, jsx_runtime_1.jsxs)(react_1.Flex, { as: interactive ? "a" : "div", ...(interactive
119
+ ? {
120
+ href: app.url,
121
+ target: "_blank",
122
+ rel: "noopener noreferrer",
123
+ "data-launcher-item": true,
124
+ onClick: (event) => onSelect(app, event),
125
+ }
126
+ : {}), "aria-current": isCurrent ? "true" : undefined, title: app.locked
127
+ ? ((_a = app.lockedReason) !== null && _a !== void 0 ? _a : `${app.name} is not available on your plan`)
128
+ : undefined, "data-app-locked": app.locked ? "true" : undefined, align: "center", gap: 3, minH: "44px", px: 2, py: 1, borderRadius: "8px", textDecoration: "none", cursor: interactive ? "pointer" : "default", bg: isCurrent ? rows.selected : "transparent", transition: (0, motion_1.transitionFor)(["background-color"]), _hover: interactive ? { bg: rows.active } : undefined, sx: ring, children: [(0, jsx_runtime_1.jsx)(AppMark_1.default, { app: app, hue: hues[index], boxSize: "28px", iconSize: 15, muted: app.locked }), (0, jsx_runtime_1.jsx)(react_1.Text, { flex: 1, minW: 0, fontSize: "sm", fontWeight: "medium", noOfLines: 1, color: app.locked ? colors.textMuted : colors.text[900], children: app.name }), app.locked ? ((0, jsx_runtime_1.jsx)(react_1.Box, { as: lucide_react_1.Lock, size: 14, color: colors.textMuted, flexShrink: 0, "aria-hidden": true })) : null] }) }, app.id || app.name));
129
+ }) })] }));
130
+ }
@@ -0,0 +1,53 @@
1
+ import type { LauncherIcon, LauncherResultGroup, LauncherSearchItem, LauncherSection } from "./NavLauncherProps";
2
+ export type LauncherResult = {
3
+ id: string;
4
+ label: string;
5
+ context?: string;
6
+ icon?: LauncherIcon;
7
+ hint?: string;
8
+ badge?: number | string;
9
+ href?: string;
10
+ run?: () => void;
11
+ screenId?: string;
12
+ /** Set on `searchLauncherSections` rows: a module row or one of its screens. */
13
+ kind?: "module" | "screen";
14
+ /** Keyword that matched a module or screen whose own name did not. */
15
+ keywordHint?: string;
16
+ isNew?: boolean;
17
+ };
18
+ export type LauncherResultView = {
19
+ id: string;
20
+ label: string;
21
+ items: LauncherResult[];
22
+ };
23
+ export declare function flattenScreens(sections: readonly LauncherSection[]): LauncherResult[];
24
+ export declare function searchLauncher(input: {
25
+ query: string;
26
+ sections: readonly LauncherSection[];
27
+ actions?: readonly LauncherSearchItem[];
28
+ extraResults?: readonly LauncherResultGroup[];
29
+ screensLabel: string;
30
+ actionsLabel: string;
31
+ }): LauncherResultView[];
32
+ export type LauncherSectionResult = {
33
+ id: string;
34
+ label: string;
35
+ items: LauncherResult[];
36
+ };
37
+ /** Search that keeps the sections: per section, matching modules, each followed by its matching screens. */
38
+ export declare function searchLauncherSections(input: {
39
+ query: string;
40
+ sections: readonly LauncherSection[];
41
+ actions?: readonly LauncherSearchItem[];
42
+ extraResults?: readonly LauncherResultGroup[];
43
+ actionsLabel: string;
44
+ }): {
45
+ sections: LauncherSectionResult[];
46
+ groups: LauncherResultView[];
47
+ };
48
+ export type HighlightSegment = {
49
+ text: string;
50
+ isMatch: boolean;
51
+ };
52
+ /** Splits `text` so every case-insensitive occurrence of a query token is its own matched segment. */
53
+ export declare function highlightSegments(text: string, query: string): HighlightSegment[];
@@ -0,0 +1,178 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.flattenScreens = flattenScreens;
4
+ exports.searchLauncher = searchLauncher;
5
+ exports.searchLauncherSections = searchLauncherSections;
6
+ exports.highlightSegments = highlightSegments;
7
+ const normalize = (text) => text.toLocaleLowerCase().normalize("NFKD");
8
+ function score(label, haystack, tokens) {
9
+ if (!tokens.every((t) => haystack.includes(t)))
10
+ return null;
11
+ const l = normalize(label);
12
+ const q = tokens.join(" ");
13
+ if (l === q)
14
+ return 0;
15
+ if (l.startsWith(q))
16
+ return 1;
17
+ if (l.split(/\s+/).some((w) => w.startsWith(tokens[0])))
18
+ return 2;
19
+ return l.includes(tokens[0]) ? 3 : 4;
20
+ }
21
+ function rank(rows, text, tokens) {
22
+ return rows
23
+ .map((row, index) => ({
24
+ row,
25
+ index,
26
+ s: score(row.label, normalize(text(row)), tokens),
27
+ }))
28
+ .filter((r) => r.s !== null)
29
+ .sort((a, b) => a.s - b.s || a.index - b.index)
30
+ .map((r) => r.row);
31
+ }
32
+ function flattenScreens(sections) {
33
+ var _a, _b, _c;
34
+ const seen = new Set();
35
+ const out = [];
36
+ for (const section of sections) {
37
+ for (const module of section.modules) {
38
+ for (const screen of module.screens) {
39
+ if (seen.has(screen.id))
40
+ continue;
41
+ seen.add(screen.id);
42
+ out.push({
43
+ id: `screen:${screen.id}`,
44
+ screenId: screen.id,
45
+ label: screen.label,
46
+ context: screen.label === module.label ? section.label : module.label,
47
+ icon: (_a = screen.icon) !== null && _a !== void 0 ? _a : module.icon,
48
+ badge: screen.badge,
49
+ href: screen.href,
50
+ keywords: [module.label, ...((_b = module.keywords) !== null && _b !== void 0 ? _b : []), ...((_c = screen.keywords) !== null && _c !== void 0 ? _c : [])].join(" "),
51
+ });
52
+ }
53
+ }
54
+ }
55
+ return out;
56
+ }
57
+ function searchLauncher(input) {
58
+ var _a, _b;
59
+ const tokens = normalize(input.query).split(/\s+/).filter(Boolean);
60
+ if (tokens.length === 0)
61
+ return [];
62
+ const screens = flattenScreens(input.sections);
63
+ const actions = rank(((_a = input.actions) !== null && _a !== void 0 ? _a : []).map((a) => ({ ...a, id: `action:${a.id}` })), (a) => { var _a, _b; return `${a.label} ${(_a = a.context) !== null && _a !== void 0 ? _a : ""} ${(_b = a.keywords) !== null && _b !== void 0 ? _b : ""}`; }, tokens);
64
+ const groups = [
65
+ { id: "actions", label: input.actionsLabel, items: actions },
66
+ {
67
+ id: "screens",
68
+ label: input.screensLabel,
69
+ items: rank(screens, (s) => { var _a; return `${s.label} ${(_a = s.context) !== null && _a !== void 0 ? _a : ""} ${s.keywords}`; }, tokens),
70
+ },
71
+ ...((_b = input.extraResults) !== null && _b !== void 0 ? _b : []).map((g) => ({
72
+ id: g.id,
73
+ label: g.label,
74
+ items: g.items.map((i) => ({ ...i, id: `${g.id}:${i.id}` })),
75
+ })),
76
+ ];
77
+ return groups.filter((g) => g.items.length > 0);
78
+ }
79
+ function matchNameOrKeyword(label, keywords, tokens) {
80
+ const name = normalize(label);
81
+ if (tokens.every((t) => name.includes(t)))
82
+ return {};
83
+ const terms = keywords.map(normalize);
84
+ const all = `${name} ${terms.join(" ")}`;
85
+ if (!tokens.every((t) => all.includes(t)))
86
+ return null;
87
+ const hit = keywords.find((_, i) => tokens.some((t) => terms[i].includes(t)));
88
+ return { keyword: hit !== null && hit !== void 0 ? hit : keywords[0] };
89
+ }
90
+ /** Search that keeps the sections: per section, matching modules, each followed by its matching screens. */
91
+ function searchLauncherSections(input) {
92
+ var _a, _b, _c, _d, _e, _f;
93
+ const tokens = normalize(input.query).split(/\s+/).filter(Boolean);
94
+ if (tokens.length === 0)
95
+ return { sections: [], groups: [] };
96
+ const seen = new Set();
97
+ const sections = [];
98
+ for (const section of input.sections) {
99
+ const items = [];
100
+ for (const module of section.modules) {
101
+ const moduleHit = matchNameOrKeyword(module.label, (_a = module.keywords) !== null && _a !== void 0 ? _a : [], tokens);
102
+ if (moduleHit) {
103
+ items.push({
104
+ id: `module:${module.id}`,
105
+ kind: "module",
106
+ label: module.label,
107
+ keywordHint: moduleHit.keyword,
108
+ icon: module.icon,
109
+ badge: module.badge,
110
+ isNew: module.isNew,
111
+ href: module.href,
112
+ screenId: (_b = module.screens[0]) === null || _b === void 0 ? void 0 : _b.id,
113
+ });
114
+ }
115
+ for (const screen of module.screens) {
116
+ if (screen.label === module.label || seen.has(screen.id))
117
+ continue;
118
+ if (!matchNameOrKeyword(screen.label, (_c = screen.keywords) !== null && _c !== void 0 ? _c : [], tokens))
119
+ continue;
120
+ seen.add(screen.id);
121
+ items.push({
122
+ id: `screen:${screen.id}`,
123
+ kind: "screen",
124
+ label: screen.label,
125
+ context: module.label,
126
+ icon: (_d = screen.icon) !== null && _d !== void 0 ? _d : module.icon,
127
+ badge: screen.badge,
128
+ href: screen.href,
129
+ });
130
+ }
131
+ }
132
+ if (items.length > 0)
133
+ sections.push({ id: section.id, label: section.label, items });
134
+ }
135
+ const actions = rank(((_e = input.actions) !== null && _e !== void 0 ? _e : []).map((a) => ({ ...a, id: `action:${a.id}` })), (a) => { var _a, _b; return `${a.label} ${(_a = a.context) !== null && _a !== void 0 ? _a : ""} ${(_b = a.keywords) !== null && _b !== void 0 ? _b : ""}`; }, tokens);
136
+ const groups = [
137
+ { id: "actions", label: input.actionsLabel, items: actions },
138
+ ...((_f = input.extraResults) !== null && _f !== void 0 ? _f : []).map((g) => ({
139
+ id: g.id,
140
+ label: g.label,
141
+ items: g.items.map((i) => ({ ...i, id: `${g.id}:${i.id}` })),
142
+ })),
143
+ ].filter((g) => g.items.length > 0);
144
+ return { sections, groups };
145
+ }
146
+ /** Splits `text` so every case-insensitive occurrence of a query token is its own matched segment. */
147
+ function highlightSegments(text, query) {
148
+ const lower = text.toLocaleLowerCase();
149
+ const tokens = query.toLocaleLowerCase().split(/\s+/).filter(Boolean);
150
+ if (tokens.length === 0 || lower.length !== text.length)
151
+ return [{ text, isMatch: false }];
152
+ const ranges = [];
153
+ for (const token of tokens) {
154
+ for (let at = lower.indexOf(token); at !== -1; at = lower.indexOf(token, at + token.length)) {
155
+ ranges.push([at, at + token.length]);
156
+ }
157
+ }
158
+ ranges.sort((a, b) => a[0] - b[0]);
159
+ const merged = [];
160
+ for (const range of ranges) {
161
+ const last = merged[merged.length - 1];
162
+ if (last && range[0] <= last[1])
163
+ last[1] = Math.max(last[1], range[1]);
164
+ else
165
+ merged.push([...range]);
166
+ }
167
+ const out = [];
168
+ let cursor = 0;
169
+ for (const [start, end] of merged) {
170
+ if (start > cursor)
171
+ out.push({ text: text.slice(cursor, start), isMatch: false });
172
+ out.push({ text: text.slice(start, end), isMatch: true });
173
+ cursor = end;
174
+ }
175
+ if (cursor < text.length)
176
+ out.push({ text: text.slice(cursor), isMatch: false });
177
+ return out.length ? out : [{ text, isMatch: false }];
178
+ }
@@ -0,0 +1,4 @@
1
+ import type { SystemStyleObject } from "@chakra-ui/react";
2
+ import type { PaletteProps } from "../../Theme/tokens/types";
3
+ /** Shows a row affordance on row hover, row focus-within or its own keyboard focus, and always on touch. */
4
+ export declare const revealStyles: (colors: PaletteProps) => SystemStyleObject;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.revealStyles = void 0;
4
+ const focusRing_styles_1 = require("../../Theme/chakra/focusRing.styles");
5
+ const motion_1 = require("../../Theme/chakra/motion");
6
+ /** Shows a row affordance on row hover, row focus-within or its own keyboard focus, and always on touch. */
7
+ const revealStyles = (colors) => {
8
+ const ring = (0, focusRing_styles_1.focusVisibleStyles)(colors);
9
+ return {
10
+ ...ring,
11
+ _focusVisible: { ...ring._focusVisible, opacity: 1 },
12
+ _groupHover: { opacity: 1 },
13
+ _groupFocusWithin: { opacity: 1 },
14
+ "[data-reveal=true] &": { opacity: 1 },
15
+ "@media (hover: none)": { opacity: 1 },
16
+ ...(0, motion_1.reducedMotionSx)(),
17
+ };
18
+ };
19
+ exports.revealStyles = revealStyles;
@@ -1,2 +1,2 @@
1
1
  import { NavbarProps } from "./NavigationBarProps";
2
- export default function NavBar({ userAvathar, userName, userRole, navMenu, moreIcon, handleNavOnClick, handleLogout, logoutText, navigationBarText, sideBarToggole, onSideBarToggole, forceSideBarToggle, onSideBarPeek, }: NavbarProps): import("react/jsx-runtime").JSX.Element;
2
+ export default function NavBar({ userAvathar, userName, userRole, navMenu, moreIcon, handleNavOnClick, handleLogout, logoutText, navigationBarText, sideBarToggole, onSideBarToggole, forceSideBarToggle, onSideBarPeek, leading, }: NavbarProps): import("react/jsx-runtime").JSX.Element;
@@ -16,7 +16,7 @@ const PersonChip_1 = __importDefault(require("../PersonChip/PersonChip"));
16
16
  const lucide_react_1 = require("lucide-react");
17
17
  // Roomy enough to hover without aiming: the glyph is only 1.25rem.
18
18
  const SIDEBAR_TOGGLE_HIT = "2.5rem";
19
- function NavBar({ userAvathar, userName, userRole, navMenu, moreIcon, handleNavOnClick, handleLogout, logoutText, navigationBarText, sideBarToggole, onSideBarToggole, forceSideBarToggle = false, onSideBarPeek, }) {
19
+ function NavBar({ userAvathar, userName, userRole, navMenu, moreIcon, handleNavOnClick, handleLogout, logoutText, navigationBarText, sideBarToggole, onSideBarToggole, forceSideBarToggle = false, onSideBarPeek, leading, }) {
20
20
  const theme = (0, useCustomTheme_1.useCustomTheme)();
21
21
  const rowBackgrounds = (0, rowStates_1.listRowBackgrounds)(theme.colors);
22
22
  const menuHoverBg = rowBackgrounds.active;
@@ -52,7 +52,7 @@ function NavBar({ userAvathar, userName, userRole, navMenu, moreIcon, handleNavO
52
52
  _focus: { bg: menuHoverBg },
53
53
  _active: { bg: rowBackgrounds.selectedActive },
54
54
  };
55
- return ((0, jsx_runtime_1.jsx)(react_1.Box, { bg: theme.colors.backgroundColor.light, px: 4, borderBottom: "1px solid", borderColor: theme.colors.boxborder[200], children: (0, jsx_runtime_1.jsxs)(react_1.Flex, { h: 16, alignItems: "center", justifyContent: "space-between", children: [(0, jsx_runtime_1.jsxs)(react_1.Box, { display: "flex", gap: 1.5, alignItems: "center", children: [(0, jsx_runtime_1.jsx)(react_1.Box, { as: "button", type: "button", onClick: () => onSideBarToggole === null || onSideBarToggole === void 0 ? void 0 : onSideBarToggole(), onMouseEnter: onSideBarPeek, onFocus: onSideBarPeek, "aria-label": sideBarToggole ? "Close navigation menu" : "Open navigation menu", "aria-expanded": !!sideBarToggole, ...iconButtonStyle, display: forceSideBarToggle ? "flex" : { base: "flex", lg: "none" }, w: SIDEBAR_TOGGLE_HIT, h: SIDEBAR_TOGGLE_HIT, children: sideBarToggole ? ((0, jsx_runtime_1.jsx)(lucide_react_1.PanelLeftClose, { size: "1.25rem" })) : ((0, jsx_runtime_1.jsx)(lucide_react_1.PanelRightClose, { size: "1.25rem" })) }), (navigationBarText === null || navigationBarText === void 0 ? void 0 : navigationBarText.onIconClick) && ((0, jsx_runtime_1.jsx)(react_1.Box, { ...iconButtonStyle, as: "button", type: "button", "aria-label": "Go back", display: "flex", onClick: () => { var _a; return (_a = navigationBarText === null || navigationBarText === void 0 ? void 0 : navigationBarText.onIconClick) === null || _a === void 0 ? void 0 : _a.call(navigationBarText); }, children: (0, jsx_runtime_1.jsx)(lucide_react_1.CircleArrowLeft, { size: "1.25rem", color: theme.colors.text[500] }) })), (navigationBarText === null || navigationBarText === void 0 ? void 0 : navigationBarText.text) && ((0, jsx_runtime_1.jsx)(react_1.Text, { color: (0, accentText_1.accentTextOnCanvas)(theme.colors.secondary, theme.colors.backgroundColor.light), fontSize: "1.25rem", fontWeight: 600, fontFamily: "open-sans, sans-serif", letterSpacing: "-0.013rem", children: navigationBarText === null || navigationBarText === void 0 ? void 0 : navigationBarText.text }))] }), (0, jsx_runtime_1.jsx)(react_1.Flex, { minW: 0, flexShrink: 1, children: (0, jsx_runtime_1.jsxs)(react_1.Stack, { direction: "row", alignItems: "center", spacing: 4, minW: 0, children: [moreIcon && ((0, jsx_runtime_1.jsx)(react_1.Box, { display: "flex", alignItems: "center", minW: 0, children: moreIcon })), (0, jsx_runtime_1.jsxs)(react_1.Menu, { children: [(0, jsx_runtime_1.jsx)(react_1.MenuButton, { as: react_1.Button, rounded: "full", variant: "link", cursor: "pointer", minW: 0, flexShrink: 0, children: (0, jsx_runtime_1.jsx)(Avatar_1.default, { size: "sm", name: userName, src: userAvathar }) }), (0, jsx_runtime_1.jsx)(react_1.MenuList, { alignItems: "center", zIndex: 5, p: 0, py: "0.375rem",
55
+ return ((0, jsx_runtime_1.jsx)(react_1.Box, { bg: theme.colors.backgroundColor.light, px: 4, borderBottom: "1px solid", borderColor: theme.colors.boxborder[200], children: (0, jsx_runtime_1.jsxs)(react_1.Flex, { h: 16, alignItems: "center", justifyContent: "space-between", children: [(0, jsx_runtime_1.jsxs)(react_1.Box, { display: "flex", gap: 1.5, alignItems: "center", children: [(0, jsx_runtime_1.jsx)(react_1.Box, { as: "button", type: "button", onClick: () => onSideBarToggole === null || onSideBarToggole === void 0 ? void 0 : onSideBarToggole(), onMouseEnter: onSideBarPeek, onFocus: onSideBarPeek, "aria-label": sideBarToggole ? "Close navigation menu" : "Open navigation menu", "aria-expanded": !!sideBarToggole, ...iconButtonStyle, display: forceSideBarToggle ? "flex" : { base: "flex", lg: "none" }, w: SIDEBAR_TOGGLE_HIT, h: SIDEBAR_TOGGLE_HIT, children: sideBarToggole ? ((0, jsx_runtime_1.jsx)(lucide_react_1.PanelLeftClose, { size: "1.25rem" })) : ((0, jsx_runtime_1.jsx)(lucide_react_1.PanelRightClose, { size: "1.25rem" })) }), (navigationBarText === null || navigationBarText === void 0 ? void 0 : navigationBarText.onIconClick) && ((0, jsx_runtime_1.jsx)(react_1.Box, { ...iconButtonStyle, as: "button", type: "button", "aria-label": "Go back", display: "flex", onClick: () => { var _a; return (_a = navigationBarText === null || navigationBarText === void 0 ? void 0 : navigationBarText.onIconClick) === null || _a === void 0 ? void 0 : _a.call(navigationBarText); }, children: (0, jsx_runtime_1.jsx)(lucide_react_1.CircleArrowLeft, { size: "1.25rem", color: theme.colors.text[500] }) })), leading && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [leading, (0, jsx_runtime_1.jsx)(react_1.Box, { as: "span", "aria-hidden": "true", mx: 2, w: "1px", h: "1.625rem", bg: theme.colors.boxborder[200] })] })), (navigationBarText === null || navigationBarText === void 0 ? void 0 : navigationBarText.text) && ((0, jsx_runtime_1.jsx)(react_1.Text, { color: (0, accentText_1.accentTextOnCanvas)(theme.colors.secondary, theme.colors.backgroundColor.light), fontSize: "1.25rem", fontWeight: 600, fontFamily: "open-sans, sans-serif", letterSpacing: "-0.013rem", children: navigationBarText === null || navigationBarText === void 0 ? void 0 : navigationBarText.text }))] }), (0, jsx_runtime_1.jsx)(react_1.Flex, { minW: 0, flexShrink: 1, children: (0, jsx_runtime_1.jsxs)(react_1.Stack, { direction: "row", alignItems: "center", spacing: 4, minW: 0, children: [moreIcon && ((0, jsx_runtime_1.jsx)(react_1.Box, { display: "flex", alignItems: "center", minW: 0, children: moreIcon })), (0, jsx_runtime_1.jsxs)(react_1.Menu, { children: [(0, jsx_runtime_1.jsx)(react_1.MenuButton, { as: react_1.Button, rounded: "full", variant: "link", cursor: "pointer", minW: 0, flexShrink: 0, children: (0, jsx_runtime_1.jsx)(Avatar_1.default, { size: "sm", name: userName, src: userAvathar }) }), (0, jsx_runtime_1.jsx)(react_1.MenuList, { alignItems: "center", zIndex: 5, p: 0, py: "0.375rem",
56
56
  // Without a cap one long title stretches the whole dropdown; titles truncate instead.
57
57
  maxW: "18rem", bg: theme.colors.surfaceRaised,
58
58
  // NOTE: Chakra's MenuItem inherits --menu-bg hardcoded to #fff via dead _dark — set it or items stay white.
@@ -28,6 +28,8 @@ export type NavbarProps = {
28
28
  * same state the SideBar's `peekOpen` reads; it closes itself when the pointer leaves.
29
29
  */
30
30
  onSideBarPeek?: () => void;
31
+ /** Rendered between the sidebar toggle/back button and the title, outside the title element, followed by a 1px divider. */
32
+ leading?: ReactNode;
31
33
  };
32
34
  /** One navMenu entry (id/title/url/icon) — unrelated to Chakra's own MenuProps despite the shared name. */
33
35
  export type MenuProps = {
@@ -1,4 +1,4 @@
1
1
  import type { PageHeaderProps } from "./PageHeaderProps";
2
2
  /** Page header: h1 title, muted subtitle, right-aligned actions that wrap under on narrow screens. */
3
- declare const PageHeader: ({ title, subtitle, actions, breadcrumbs, leading, titleAddon, meta, tabs, "data-testid": testId, }: PageHeaderProps) => import("react/jsx-runtime").JSX.Element;
3
+ declare const PageHeader: ({ title, subtitle, actions, breadcrumbs, leading, titleAddon, meta, tabs, titleSize, actionsLayout, "data-testid": testId, }: PageHeaderProps) => import("react/jsx-runtime").JSX.Element;
4
4
  export default PageHeader;
@@ -3,9 +3,16 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const jsx_runtime_1 = require("react/jsx-runtime");
4
4
  const react_1 = require("@chakra-ui/react");
5
5
  const useCustomTheme_1 = require("../../Theme/useCustomTheme");
6
+ const TITLE_STYLES = {
7
+ md: { fontSize: "lg", fontWeight: 600, letterSpacing: "-0.01em" },
8
+ lg: { fontSize: "2xl", fontWeight: 700, letterSpacing: "-0.02em", lineHeight: 1.2 },
9
+ xl: { fontSize: { base: "2xl", md: "3xl" }, fontWeight: 700, letterSpacing: "-0.025em", lineHeight: 1.2 },
10
+ };
6
11
  /** Page header: h1 title, muted subtitle, right-aligned actions that wrap under on narrow screens. */
7
- const PageHeader = ({ title, subtitle, actions, breadcrumbs, leading, titleAddon, meta, tabs, "data-testid": testId, }) => {
12
+ const PageHeader = ({ title, subtitle, actions, breadcrumbs, leading, titleAddon, meta, tabs, titleSize = "md", actionsLayout = "auto", "data-testid": testId, }) => {
8
13
  const { colors } = (0, useCustomTheme_1.useCustomTheme)();
9
- return ((0, jsx_runtime_1.jsxs)(react_1.Flex, { direction: "column", gap: 3, "data-testid": testId, children: [breadcrumbs && ((0, jsx_runtime_1.jsx)(react_1.Box, { fontSize: "sm", color: colors.textMuted, sx: { "[aria-current=page]": { color: colors.text[800] } }, children: breadcrumbs })), (0, jsx_runtime_1.jsxs)(react_1.Flex, { justify: "space-between", align: { base: "flex-start", md: "center" }, direction: { base: "column", md: "row" }, gap: 3, children: [(0, jsx_runtime_1.jsxs)(react_1.Flex, { gap: 3, align: "center", minW: 0, children: [leading && (0, jsx_runtime_1.jsx)(react_1.Box, { flexShrink: 0, children: leading }), (0, jsx_runtime_1.jsxs)(react_1.Box, { minW: 0, children: [(0, jsx_runtime_1.jsxs)(react_1.Flex, { align: "center", gap: 2, wrap: "wrap", children: [(0, jsx_runtime_1.jsx)(react_1.Heading, { as: "h1", fontSize: "lg", fontWeight: 600, letterSpacing: "-0.01em", color: colors.header[900], children: title }), titleAddon] }), subtitle && ((0, jsx_runtime_1.jsx)(react_1.Text, { mt: 0.5, fontSize: "sm", color: colors.textMuted, children: subtitle })), meta && ((0, jsx_runtime_1.jsx)(react_1.Flex, { mt: 1, columnGap: 4, rowGap: 1, wrap: "wrap", align: "center", fontSize: "xs", color: colors.textMuted, children: meta }))] })] }), actions && ((0, jsx_runtime_1.jsx)(react_1.Flex, { gap: 2, wrap: "wrap", align: "center", flexShrink: 0, children: actions }))] }), tabs && (0, jsx_runtime_1.jsx)(react_1.Box, { children: tabs })] }));
14
+ const wraps = actionsLayout === "auto";
15
+ const stacked = actionsLayout === "stacked";
16
+ return ((0, jsx_runtime_1.jsxs)(react_1.Flex, { direction: "column", gap: 3, "data-testid": testId, children: [breadcrumbs && ((0, jsx_runtime_1.jsx)(react_1.Box, { fontSize: "sm", color: colors.textMuted, sx: { "[aria-current=page]": { color: colors.text[800] } }, children: breadcrumbs })), (0, jsx_runtime_1.jsxs)(react_1.Flex, { justify: "space-between", align: stacked ? "flex-start" : { base: "flex-start", md: "center" }, direction: stacked ? "column" : { base: "column", md: "row" }, wrap: wraps ? "wrap" : "nowrap", gap: 3, children: [(0, jsx_runtime_1.jsxs)(react_1.Flex, { gap: 3, align: "center", minW: 0, flex: wraps ? { base: "0 1 auto", md: "1 1 16rem" } : undefined, children: [leading && (0, jsx_runtime_1.jsx)(react_1.Box, { flexShrink: 0, children: leading }), (0, jsx_runtime_1.jsxs)(react_1.Box, { minW: 0, children: [(0, jsx_runtime_1.jsxs)(react_1.Flex, { align: "center", gap: 2, wrap: "wrap", children: [(0, jsx_runtime_1.jsx)(react_1.Heading, { as: "h1", ...TITLE_STYLES[titleSize], color: colors.header[900], children: title }), titleAddon] }), subtitle && ((0, jsx_runtime_1.jsx)(react_1.Text, { mt: 0.5, fontSize: "sm", color: colors.textMuted, children: subtitle })), meta && ((0, jsx_runtime_1.jsx)(react_1.Flex, { mt: 1, columnGap: 4, rowGap: 1, wrap: "wrap", align: "center", fontSize: "xs", color: colors.textMuted, children: meta }))] })] }), actions && ((0, jsx_runtime_1.jsx)(react_1.Flex, { gap: 2, wrap: "wrap", align: "center", flexShrink: wraps ? undefined : 0, children: actions }))] }), tabs && (0, jsx_runtime_1.jsx)(react_1.Box, { children: tabs })] }));
10
17
  };
11
18
  exports.default = PageHeader;
@@ -16,5 +16,13 @@ export interface PageHeaderProps {
16
16
  meta?: ReactNode;
17
17
  /** Rendered full-width below the whole header, e.g. a Tabs list. */
18
18
  tabs?: ReactNode;
19
+ /** "md" = 18px/600 (default); "lg" = 24px/700; "xl" = 24px, 30px from `md`, 700, tighter tracking. */
20
+ titleSize?: PageHeaderTitleSize;
21
+ /** "auto" (default) wraps actions below the title whenever they don't fit beside it; "stacked" always stacks; "inline" never wraps from `md` up. */
22
+ actionsLayout?: PageHeaderActionsLayout;
19
23
  "data-testid"?: string;
20
24
  }
25
+ /** Title ramp step. */
26
+ export type PageHeaderTitleSize = "md" | "lg" | "xl";
27
+ /** How the actions row sits against the title block. */
28
+ export type PageHeaderActionsLayout = "auto" | "stacked" | "inline";