@activecollab/components 2.0.418 → 2.0.419

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 (59) hide show
  1. package/dist/cjs/components/Icons/collection/Portfolio.js +61 -0
  2. package/dist/cjs/components/Icons/collection/Portfolio.js.map +1 -0
  3. package/dist/cjs/components/Icons/collection/PortfolioPlus.js +62 -0
  4. package/dist/cjs/components/Icons/collection/PortfolioPlus.js.map +1 -0
  5. package/dist/cjs/components/Icons/collection/Target.js +65 -0
  6. package/dist/cjs/components/Icons/collection/Target.js.map +1 -0
  7. package/dist/cjs/components/Icons/collection/index.js +21 -0
  8. package/dist/cjs/components/Icons/collection/index.js.map +1 -1
  9. package/dist/cjs/presentation/shared/PortfolioOptionsMenu.js +64 -0
  10. package/dist/cjs/presentation/shared/PortfolioOptionsMenu.js.map +1 -0
  11. package/dist/cjs/presentation/shared/ProjectOptionsMenu.js +367 -0
  12. package/dist/cjs/presentation/shared/ProjectOptionsMenu.js.map +1 -0
  13. package/dist/cjs/presentation/shared/dashboardWidgets.js +726 -0
  14. package/dist/cjs/presentation/shared/dashboardWidgets.js.map +1 -0
  15. package/dist/cjs/presentation/shared/headers.js +25 -360
  16. package/dist/cjs/presentation/shared/headers.js.map +1 -1
  17. package/dist/cjs/presentation/shared/index.js +108 -0
  18. package/dist/cjs/presentation/shared/index.js.map +1 -1
  19. package/dist/esm/components/Icons/collection/Portfolio.d.ts +32 -0
  20. package/dist/esm/components/Icons/collection/Portfolio.d.ts.map +1 -0
  21. package/dist/esm/components/Icons/collection/Portfolio.js +54 -0
  22. package/dist/esm/components/Icons/collection/Portfolio.js.map +1 -0
  23. package/dist/esm/components/Icons/collection/PortfolioPlus.d.ts +32 -0
  24. package/dist/esm/components/Icons/collection/PortfolioPlus.d.ts.map +1 -0
  25. package/dist/esm/components/Icons/collection/PortfolioPlus.js +55 -0
  26. package/dist/esm/components/Icons/collection/PortfolioPlus.js.map +1 -0
  27. package/dist/esm/components/Icons/collection/Target.d.ts +32 -0
  28. package/dist/esm/components/Icons/collection/Target.d.ts.map +1 -0
  29. package/dist/esm/components/Icons/collection/Target.js +58 -0
  30. package/dist/esm/components/Icons/collection/Target.js.map +1 -0
  31. package/dist/esm/components/Icons/collection/index.d.ts +3 -0
  32. package/dist/esm/components/Icons/collection/index.d.ts.map +1 -1
  33. package/dist/esm/components/Icons/collection/index.js +3 -0
  34. package/dist/esm/components/Icons/collection/index.js.map +1 -1
  35. package/dist/esm/presentation/shared/PortfolioOptionsMenu.d.ts +12 -0
  36. package/dist/esm/presentation/shared/PortfolioOptionsMenu.d.ts.map +1 -0
  37. package/dist/esm/presentation/shared/PortfolioOptionsMenu.js +46 -0
  38. package/dist/esm/presentation/shared/PortfolioOptionsMenu.js.map +1 -0
  39. package/dist/esm/presentation/shared/ProjectOptionsMenu.d.ts +31 -0
  40. package/dist/esm/presentation/shared/ProjectOptionsMenu.d.ts.map +1 -0
  41. package/dist/esm/presentation/shared/ProjectOptionsMenu.js +311 -0
  42. package/dist/esm/presentation/shared/ProjectOptionsMenu.js.map +1 -0
  43. package/dist/esm/presentation/shared/dashboardWidgets.d.ts +203 -0
  44. package/dist/esm/presentation/shared/dashboardWidgets.d.ts.map +1 -0
  45. package/dist/esm/presentation/shared/dashboardWidgets.js +665 -0
  46. package/dist/esm/presentation/shared/dashboardWidgets.js.map +1 -0
  47. package/dist/esm/presentation/shared/headers.d.ts +0 -11
  48. package/dist/esm/presentation/shared/headers.d.ts.map +1 -1
  49. package/dist/esm/presentation/shared/headers.js +23 -315
  50. package/dist/esm/presentation/shared/headers.js.map +1 -1
  51. package/dist/esm/presentation/shared/index.d.ts +6 -0
  52. package/dist/esm/presentation/shared/index.d.ts.map +1 -1
  53. package/dist/esm/presentation/shared/index.js +3 -0
  54. package/dist/esm/presentation/shared/index.js.map +1 -1
  55. package/dist/index.js +666 -508
  56. package/dist/index.js.map +1 -1
  57. package/dist/index.min.js +1 -1
  58. package/dist/index.min.js.map +1 -1
  59. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboardWidgets.js","names":["React","useState","styled","LG","MD","SM","IconButton","InfoSmallIcon","SortListIcon","ProgressBar","ProgressRing","Select","Tooltip","Body1","Body2","Header2","Title2","ValueButton","colors","FONT_STACK","TICK_COLOR","CHART_SERIES_COLORS","blueSky","color","coral","greenPale","orange","purple","pink","OVERVIEW_SECTION_COLORS","tasks","track","time","budget","WidgetGrid","div","withConfig","displayName","componentId","WidgetGroupBy","_ref","_options$","options","initial","onChange","_useState","id","selected","setSelected","_useState2","open","setOpen","createElement","value","String","onSelectOpen","onSelectClose","position","forceCloseMenu","disableSearch","keepSameOptionsOrder","disabledInternalSort","target","type","variant","active","fill","PERIOD_OPTIONS","name","PeriodPicker","_ref2","_PERIOD_OPTIONS$find$","_PERIOD_OPTIONS$find","_useState3","find","option","next","label","StyledWidget","greenSuccess","StatWidget","_ref3","unit","title","description","linkText","alert","success","groupBy","cornerControl","children","className","weight","overflow","whitespace","StyledRankedList","WidgetRankedList","_ref4","items","map","item","key","RING_RADII","RING_STROKE","StyledOverview","ringColor","section","hovered","progress","ringTrack","trackColor","OverviewSection","_ref5","onHover","onMouseEnter","onMouseLeave","style","backgroundColor","lineHeight","explainer","OverviewWidget","_ref6","subtitle","sections","headerRight","_useState4","setHovered","nestRings","index","roundStroke","stroke","radius","progressColor","PLOT_HEIGHT","StyledChartWidget","ChartHead","_ref7","AREA_LINE","AreaChartWidget","_ref8","points","xLabels","yTicks","min","Math","max","range","W","toXY","x","length","y","toFixed","linePoints","join","areaPoints","tick","top","width","height","viewBox","preserveAspectRatio","display","x1","y1","x2","y2","offset","stopColor","strokeWidth","vectorEffect","DELTA_UP","DELTA_DOWN","StyledDeltaBars","DailyDeltaChartWidget","_ref9","data","upMax","downMax","yTicksUp","yTicksDown","upFrac","zeroTop","tickTop","below","point","up","bottom","down","StyledLeaderboard","LeaderboardWidget","_ref0","rows","row","percentOfMax","billableShare","StyledStackedChart","StackedBarChartWidget","_ref1","total","seriesLabels","_ref1$barWidth","barWidth","_ref1$height","column","segments","_seriesLabels$index"],"sources":["../../../../src/presentation/shared/dashboardWidgets.tsx"],"sourcesContent":["import React, { ReactElement, ReactNode, useState } from \"react\";\n\nimport styled from \"styled-components\";\n\nimport { LG, MD, SM } from \"./tokens\";\nimport { IconButton } from \"../../components/IconButton\";\nimport { InfoSmallIcon, SortListIcon } from \"../../components/Icons\";\nimport { ProgressBar } from \"../../components/ProgressBar\";\nimport { ProgressRing } from \"../../components/ProgressRing\";\nimport { Select } from \"../../components/Select\";\nimport { Tooltip } from \"../../components/Tooltip\";\nimport { Body1, Body2, Header2, Title2 } from \"../../components/Typography\";\nimport { ValueButton } from \"../../components/ValueButton\";\nimport { colors } from \"../../utils/colors\";\n\n/*\n Reusable dashboard widgets for the Presentation mock-ups.\n\n These mirror the REAL report widgets in new-activecollab-front\n (src/pages/Reports/Widgets/*): Widget.js (the stat card), WidgetList.js\n (the striped ranked list), ProjectsOverview.js (accent-line sections +\n nested ProgressRings), DailyOpenTasksWidget.js (area line chart),\n DailyCreatedAndCompletedTasksWidget.js (daily +/- bars),\n LeaderboardWidget.js and TotalTrackedHoursChart.js (stacked columns).\n Dimensions, type sizes and colours are copied from that code so any\n dashboard mock built from these reads exactly like the app; the charts are\n plain SVG/CSS here (no chart.js in this Storybook).\n\n Data colours (chart palette, tick grey #89898e) are hardcoded on purpose —\n they are data, not theme — while all structure uses var(--…) tokens.\n*/\n\n/* Raw (non-Typography) text needs an explicit font — no global reset here. */\nconst FONT_STACK =\n '-apple-system, BlinkMacSystemFont, \"Roboto\", \"Helvetica Neue\", Arial, sans-serif';\n\n/** Axis-tick grey, same literal the real chart widgets use. */\nconst TICK_COLOR = \"#89898e\";\n\n/** Stacked-chart series palette, same order as TotalTrackedHoursChart.js. */\nexport const CHART_SERIES_COLORS: string[] = [\n colors.blueSky.color,\n colors.coral.color,\n colors.greenPale.color,\n colors.orange.color,\n colors.purple.color,\n colors.pink.color,\n];\n\n/** Ring/section colour pairs used by the app's Projects Overview widget. */\nexport const OVERVIEW_SECTION_COLORS = {\n tasks: { color: colors.purple.color, track: \"rgba(190, 172, 249, 0.2)\" },\n time: { color: colors.blueSky.color, track: \"rgba(163, 205, 255, 0.2)\" },\n budget: { color: colors.greenPale.color, track: \"rgba(195, 231, 153, 0.2)\" },\n};\n\n/* ------------------------------------------------------------------ */\n/* Widget grid (mirrors AssignmentsDashboardGrid.js) */\n/* ------------------------------------------------------------------ */\n\n/*\n The dashboard grid: 24px gaps, 192px rows, 1/2/3/4 columns by breakpoint.\n Put DS <Paper type=\"paper-2\"> cells directly inside and size them with:\n .cell-overview — the big overview card (2×2 on desktop)\n .cell-tall — a 1×2 card (ranked lists)\n .cell-wide — a full-width row (charts)\n Plain cells are 1×1 (stat cards).\n*/\nexport const WidgetGrid = styled.div`\n display: grid;\n gap: 24px;\n width: 100%;\n max-width: 1440px;\n margin: 0 auto 32px;\n grid-template-columns: repeat(1, minmax(0, 1fr));\n grid-auto-rows: 192px;\n\n @media (min-width: ${SM}) {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n }\n\n @media (min-width: ${MD}) {\n grid-template-columns: repeat(3, minmax(0, 1fr));\n }\n\n @media (min-width: ${LG}) {\n grid-template-columns: repeat(4, minmax(0, 1fr));\n }\n\n > .cell-overview {\n grid-row: span 3;\n\n @media (min-width: ${SM}) {\n grid-row: span 2;\n grid-column: span 2;\n }\n\n @media (min-width: ${MD}) {\n grid-column: span 3;\n }\n\n @media (min-width: ${LG}) {\n grid-column: span 2;\n }\n }\n\n > .cell-tall {\n grid-row: span 2;\n }\n\n > .cell-wide {\n @media (min-width: ${SM}) {\n grid-column: span 2;\n }\n\n @media (min-width: ${MD}) {\n grid-column: span 3;\n }\n\n @media (min-width: ${LG}) {\n grid-column: span 4;\n }\n }\n`;\n\nWidgetGrid.displayName = \"WidgetGrid\";\n\n/* ------------------------------------------------------------------ */\n/* Group-by picker (mirrors WidgetTarget in Widget.js) */\n/* ------------------------------------------------------------------ */\n\nexport interface WidgetGroupByProps {\n options: { id: string; name: string }[];\n /** Initially selected option id (the mock keeps its own state after that). */\n initial?: string;\n onChange?: (id: string) => void;\n}\n\n/** The sort-lines icon button + radio list every widget corner uses. */\nexport const WidgetGroupBy = ({\n options,\n initial,\n onChange,\n}: WidgetGroupByProps): ReactElement => {\n const [selected, setSelected] = useState(initial ?? options[0]?.id);\n const [open, setOpen] = useState(false);\n return (\n <Select\n options={options}\n selected={selected}\n onChange={(value) => {\n setSelected(String(value));\n onChange?.(String(value));\n }}\n onSelectOpen={() => setOpen(true)}\n onSelectClose={() => setOpen(false)}\n position=\"bottom-end\"\n forceCloseMenu\n disableSearch\n keepSameOptionsOrder\n disabledInternalSort\n target={\n <IconButton type=\"button\" variant=\"text gray\" active={open}>\n <SortListIcon fill=\"var(--color-theme-800)\" />\n </IconButton>\n }\n />\n );\n};\n\nWidgetGroupBy.displayName = \"WidgetGroupBy\";\n\n/* ------------------------------------------------------------------ */\n/* Time-period picker (the completed widgets' shared control) */\n/* ------------------------------------------------------------------ */\n\n/** The app's completed-widget periods (CompletedWidgetTarget radio list). */\nexport const PERIOD_OPTIONS = [\n { id: \"this_week\", name: \"This Week\" },\n { id: \"last_week\", name: \"Last Week\" },\n { id: \"this_month\", name: \"This Month\" },\n { id: \"last_month\", name: \"Last Month\" },\n { id: \"this_quarter\", name: \"This Quarter\" },\n { id: \"last_quarter\", name: \"Last Quarter\" },\n { id: \"this_year\", name: \"This Year\" },\n { id: \"last_year\", name: \"Last Year\" },\n];\n\nexport interface PeriodPickerProps {\n selected: string;\n onChange: (id: string) => void;\n}\n\n/** One labelled period control (ValueButton + radio list) that a whole\n * section of period-scoped widgets can share. */\nexport const PeriodPicker = ({\n selected,\n onChange,\n}: PeriodPickerProps): ReactElement => {\n const [open, setOpen] = useState(false);\n const value =\n PERIOD_OPTIONS.find((option) => option.id === selected)?.name ?? \"\";\n return (\n <Select\n options={PERIOD_OPTIONS}\n selected={selected}\n onChange={(next) => onChange(String(next))}\n onSelectOpen={() => setOpen(true)}\n onSelectClose={() => setOpen(false)}\n position=\"bottom-end\"\n forceCloseMenu\n disableSearch\n keepSameOptionsOrder\n disabledInternalSort\n target={<ValueButton active={open} label=\"Period\" value={value} />}\n />\n );\n};\n\nPeriodPicker.displayName = \"PeriodPicker\";\n\n/* ------------------------------------------------------------------ */\n/* Stat widget (mirrors Widget.js) */\n/* ------------------------------------------------------------------ */\n\nconst StyledWidget = styled.div`\n position: relative;\n height: 100%;\n padding: 16px 20px;\n box-sizing: border-box;\n overflow: hidden;\n\n .widget-top {\n display: flex;\n justify-content: space-between;\n gap: 8px;\n }\n\n /* corner adornments: a target flag and/or the group-by picker together */\n .widget-corner {\n display: flex;\n align-items: center;\n gap: 4px;\n flex-shrink: 0;\n }\n\n /* the 52px total (tw-text-[52px] tw-h-14 in the app) */\n .widget-total {\n display: flex;\n width: 100%;\n height: 56px;\n margin-bottom: 8px;\n font-family: ${FONT_STACK};\n font-size: 52px;\n font-weight: 700;\n line-height: 1;\n color: var(--color-theme-900);\n }\n\n .widget-total.alert {\n color: var(--red-alert);\n }\n\n /* green treatment (e.g. positive profit), same green the app uses */\n .widget-total.success {\n color: ${colors.greenSuccess.color};\n }\n\n /* muted unit beside the total (\"H\", \"USD\"), like the Invoices tab cards */\n .widget-total .widget-unit {\n align-self: center;\n margin-left: 10px;\n font-size: 20px;\n font-weight: 600;\n line-height: 1;\n color: var(--color-theme-600);\n }\n\n .widget-title {\n margin-bottom: 8px;\n }\n\n .widget-desc {\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n height: 40px;\n margin-bottom: 8px;\n }\n\n .widget-link {\n display: inline-flex;\n cursor: pointer;\n text-decoration: none;\n }\n`;\n\nexport interface StatWidgetProps {\n /** Preformatted total (\"135\", \"1.4K\"). */\n value: string;\n /** Muted unit beside the total (\"H\", \"USD\"). */\n unit?: string;\n title: string;\n description: string;\n linkText?: string;\n /** Red treatment (overdue / underestimated above zero). */\n alert?: boolean;\n /** Green treatment (e.g. positive profit). */\n success?: boolean;\n /** Group-by picker in the top-right corner. */\n groupBy?: WidgetGroupByProps;\n /** Alternative top-right adornment (e.g. a period icon). */\n cornerControl?: ReactNode;\n /** Extra content between description and link (e.g. WidgetRankedList). */\n children?: ReactNode;\n}\n\nexport const StatWidget = ({\n value,\n unit,\n title,\n description,\n linkText,\n alert,\n success,\n groupBy,\n cornerControl,\n children,\n}: StatWidgetProps): ReactElement => (\n <StyledWidget>\n <div className=\"widget-top\">\n <span\n className={\n alert\n ? \"widget-total alert\"\n : success\n ? \"widget-total success\"\n : \"widget-total\"\n }\n >\n {value}\n {unit ? <span className=\"widget-unit\">{unit}</span> : null}\n </span>\n {cornerControl || groupBy ? (\n <span className=\"widget-corner\">\n {cornerControl}\n {groupBy ? <WidgetGroupBy {...groupBy} /> : null}\n </span>\n ) : null}\n </div>\n <Body1\n weight=\"bold\"\n color={alert ? \"alert\" : \"primary\"}\n overflow=\"truncate\"\n whitespace=\"no-wrap\"\n className=\"widget-title\"\n >\n {title}\n </Body1>\n <Body2 color=\"tertiary\" className=\"widget-desc\">\n {description}\n </Body2>\n {children}\n {linkText ? (\n <a className=\"widget-link\">\n <Body2 color=\"theme-primary\" weight=\"medium\">\n {linkText}\n </Body2>\n </a>\n ) : null}\n </StyledWidget>\n);\n\nStatWidget.displayName = \"StatWidget\";\n\n/* ------------------------------------------------------------------ */\n/* Ranked list (mirrors WidgetList.js) */\n/* ------------------------------------------------------------------ */\n\nexport interface RankedListItem {\n name: string;\n value: string;\n}\n\nconst StyledRankedList = styled.div`\n height: 216px;\n overflow-y: auto;\n padding: 4px 0;\n\n .ranked-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 4px;\n height: 24px;\n padding: 0 6px;\n margin-bottom: 4px;\n border-radius: 2px;\n box-sizing: border-box;\n }\n\n .ranked-row:nth-child(odd) {\n background-color: var(--color-theme-200);\n }\n\n .ranked-name {\n min-width: 0;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n }\n\n .ranked-value {\n flex-shrink: 0;\n }\n`;\n\n/** The striped name/count rows inside a tall stat widget. */\nexport const WidgetRankedList = ({\n items,\n}: {\n items: RankedListItem[];\n}): ReactElement => (\n <StyledRankedList>\n {items.map((item) => (\n <div className=\"ranked-row\" key={item.name}>\n <Body2 color=\"secondary\" className=\"ranked-name\">\n {item.name}\n </Body2>\n <Body2 color=\"secondary\" className=\"ranked-value\">\n {item.value}\n </Body2>\n </div>\n ))}\n </StyledRankedList>\n);\n\nWidgetRankedList.displayName = \"WidgetRankedList\";\n\n/* ------------------------------------------------------------------ */\n/* Overview widget (mirrors ProjectsOverview.js) */\n/* ------------------------------------------------------------------ */\n\nexport interface OverviewSectionData {\n id: string;\n /** Preformatted pair (\"956 of 1.4K\", \"1.2K / 8.3K\"). */\n value: string;\n /** Muted unit after the value (\"Hours\", \"USD\"). */\n unit?: string;\n description: string;\n /** Info-icon tooltip next to the description. */\n explainer?: string;\n linkText: string;\n /** Accent-line + ring colour (a data colour). */\n color: string;\n /** Ring track colour (the translucent tint of `color`). */\n trackColor: string;\n /** 0–100+; above 100 the section and its ring go red. */\n progress: number;\n}\n\nexport interface OverviewWidgetProps {\n title: string;\n subtitle: string;\n /** Up to three sections, outer ring first. */\n sections: OverviewSectionData[];\n /** Top-right control (e.g. the currency picker). */\n headerRight?: ReactNode;\n}\n\nconst RING_RADII = [121, 93, 63];\nconst RING_STROKE = 20;\n\nconst StyledOverview = styled.div`\n position: relative;\n display: flex;\n flex-direction: column;\n height: 100%;\n padding: 16px 20px;\n box-sizing: border-box;\n overflow: hidden;\n\n .overview-head {\n display: flex;\n justify-content: space-between;\n gap: 8px;\n }\n\n .overview-body {\n display: flex;\n flex-direction: column-reverse;\n justify-content: space-between;\n gap: 4px;\n height: 100%;\n\n @media (min-width: ${SM}) {\n flex-direction: row;\n margin-top: 48px;\n }\n }\n\n .overview-sections {\n display: flex;\n flex-direction: column;\n gap: 24px;\n width: 100%;\n height: fit-content;\n\n @media (min-width: ${SM}) {\n height: 100%;\n }\n }\n\n .overview-section {\n display: flex;\n width: fit-content;\n height: fit-content;\n }\n\n .overview-line {\n width: 2px;\n margin-right: 12px;\n align-self: stretch;\n flex-shrink: 0;\n }\n\n .overview-value {\n height: 28px;\n margin-bottom: 2px;\n }\n\n .overview-value-row {\n display: flex;\n align-items: flex-end;\n gap: 4px;\n }\n\n .overview-desc {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n\n .overview-desc svg {\n cursor: help;\n flex-shrink: 0;\n }\n\n .overview-link {\n display: inline-flex;\n margin-top: 4px;\n cursor: pointer;\n text-decoration: none;\n }\n\n .overview-rings {\n display: flex;\n align-self: center;\n\n @media (min-width: ${SM}) {\n align-self: flex-end;\n }\n }\n\n /* on small screens shrink the rings instead of overflowing */\n @media (max-width: 639px) {\n .overview-rings {\n transform: scale(0.6);\n transform-origin: center;\n margin: -48px 0;\n }\n }\n`;\n\nconst ringColor = (\n section: OverviewSectionData,\n hovered: string | null\n): string => {\n const active = !hovered || hovered === section.id;\n if (section.progress > 100) {\n return active ? \"var(--red-alert)\" : \"rgba(237, 97, 97, 0.25)\";\n }\n return active ? section.color : \"var(--color-theme-200)\";\n};\n\nconst ringTrack = (\n section: OverviewSectionData,\n hovered: string | null\n): string => {\n const active = !hovered || hovered === section.id;\n return active ? section.trackColor : \"var(--color-theme-200)\";\n};\n\nconst OverviewSection = ({\n section,\n onHover,\n}: {\n section: OverviewSectionData;\n onHover: (id: string | null) => void;\n}): ReactElement => {\n const alert = section.progress > 100;\n return (\n <div\n className=\"overview-section\"\n onMouseEnter={() => onHover(section.id)}\n onMouseLeave={() => onHover(null)}\n >\n <span\n className=\"overview-line\"\n style={{\n backgroundColor: alert ? \"var(--red-alert)\" : section.color,\n }}\n />\n <div>\n <div className=\"overview-value\">\n <Title2\n lineHeight=\"tight\"\n weight=\"bold\"\n color={alert ? \"alert\" : \"primary\"}\n >\n <span className=\"overview-value-row\">\n {section.value}\n {section.unit ? (\n <Body2 color=\"tertiary\">{section.unit}</Body2>\n ) : null}\n </span>\n </Title2>\n </div>\n <div className=\"overview-desc\">\n <Body2 color=\"tertiary\">{section.description}</Body2>\n {section.explainer ? (\n <Tooltip title={section.explainer}>\n <InfoSmallIcon />\n </Tooltip>\n ) : null}\n </div>\n <a className=\"overview-link\">\n <Body2 color=\"theme-primary\" weight=\"medium\">\n {section.linkText}\n </Body2>\n </a>\n </div>\n </div>\n );\n};\n\n/** The big overview card: accent-line metric sections + nested rings.\n * Hovering a section highlights its ring and mutes the other rings,\n * exactly like the app's Projects Overview. */\nexport const OverviewWidget = ({\n title,\n subtitle,\n sections,\n headerRight,\n}: OverviewWidgetProps): ReactElement => {\n const [hovered, setHovered] = useState<string | null>(null);\n\n const nestRings = (index: number): ReactElement | null => {\n const section = sections[index];\n if (!section) {\n return null;\n }\n return (\n <ProgressRing\n roundStroke\n progress={section.progress}\n stroke={RING_STROKE}\n radius={RING_RADII[index]}\n progressColor={ringColor(section, hovered)}\n backgroundColor={ringTrack(section, hovered)}\n >\n {nestRings(index + 1)}\n </ProgressRing>\n );\n };\n\n return (\n <StyledOverview>\n <div className=\"overview-head\">\n <div>\n <Body1 weight=\"bold\">{title}</Body1>\n <Body2 color=\"secondary\">{subtitle}</Body2>\n </div>\n {headerRight}\n </div>\n <div className=\"overview-body\">\n <div className=\"overview-sections\">\n {sections.map((section) => (\n <OverviewSection\n key={section.id}\n section={section}\n onHover={setHovered}\n />\n ))}\n </div>\n <div className=\"overview-rings\">{nestRings(0)}</div>\n </div>\n </StyledOverview>\n );\n};\n\nOverviewWidget.displayName = \"OverviewWidget\";\n\n/* ------------------------------------------------------------------ */\n/* Chart scaffolding shared by the chart widgets */\n/* ------------------------------------------------------------------ */\n\nconst PLOT_HEIGHT = 116;\n\nconst StyledChartWidget = styled.div`\n position: relative;\n height: 100%;\n padding: 16px 20px 0;\n box-sizing: border-box;\n overflow: hidden;\n\n .chart-head {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 8px;\n margin-bottom: 8px;\n }\n\n .chart-link {\n display: inline-flex;\n cursor: pointer;\n text-decoration: none;\n flex-shrink: 0;\n }\n\n .chart-row {\n display: flex;\n gap: 10px;\n }\n\n .chart-y-axis {\n position: relative;\n width: 30px;\n height: ${PLOT_HEIGHT}px;\n flex-shrink: 0;\n }\n\n .chart-y-tick {\n position: absolute;\n right: 0;\n transform: translateY(-50%);\n font-family: ${FONT_STACK};\n font-size: 11px;\n color: ${TICK_COLOR};\n white-space: nowrap;\n }\n\n .chart-plot {\n position: relative;\n flex: 1;\n min-width: 0;\n height: ${PLOT_HEIGHT}px;\n }\n\n .chart-x-axis {\n display: flex;\n justify-content: space-between;\n margin-top: 6px;\n padding-left: 40px;\n font-family: ${FONT_STACK};\n font-size: 11px;\n color: ${TICK_COLOR};\n }\n\n .chart-x-axis span {\n white-space: nowrap;\n }\n`;\n\nconst ChartHead = ({\n title,\n linkText,\n}: {\n title: string;\n linkText?: string;\n}): ReactElement => (\n <div className=\"chart-head\">\n <Body1 weight=\"bold\" overflow=\"truncate\" whitespace=\"no-wrap\">\n {title}\n </Body1>\n {linkText ? (\n <a className=\"chart-link\">\n <Body2 color=\"theme-primary\" weight=\"medium\">\n {linkText}\n </Body2>\n </a>\n ) : null}\n </div>\n);\n\n/* ------------------------------------------------------------------ */\n/* Area line chart (mirrors DailyOpenTasksWidget.js) */\n/* ------------------------------------------------------------------ */\n\n/** Line + gradient fill colours from the real widget. */\nconst AREA_LINE = \"#A3CDFF\";\n\nexport interface AreaChartWidgetProps {\n title: string;\n linkText?: string;\n /** The series, one value per day. */\n points: number[];\n /** X labels, spread evenly under the plot (pass a subset). */\n xLabels: string[];\n /** Y tick values; min/max define the scale. */\n yTicks: number[];\n}\n\n/** Sharp-edged line with a soft gradient below, like \"Number of Open Tasks\". */\nexport const AreaChartWidget = ({\n title,\n linkText,\n points,\n xLabels,\n yTicks,\n}: AreaChartWidgetProps): ReactElement => {\n const min = Math.min(...yTicks);\n const max = Math.max(...yTicks);\n const range = max - min || 1;\n const W = 1000;\n\n const toXY = (value: number, index: number): string => {\n const x = (index / Math.max(points.length - 1, 1)) * W;\n const y = ((max - value) / range) * PLOT_HEIGHT;\n return `${x.toFixed(1)},${y.toFixed(1)}`;\n };\n\n const linePoints = points.map(toXY).join(\" \");\n const areaPoints = `0,${PLOT_HEIGHT} ${linePoints} ${W},${PLOT_HEIGHT}`;\n\n return (\n <StyledChartWidget>\n <ChartHead title={title} linkText={linkText} />\n <div className=\"chart-row\">\n <div className=\"chart-y-axis\">\n {yTicks.map((tick) => (\n <span\n key={tick}\n className=\"chart-y-tick\"\n style={{ top: `${((max - tick) / range) * PLOT_HEIGHT}px` }}\n >\n {tick}\n </span>\n ))}\n </div>\n <div className=\"chart-plot\">\n <svg\n width=\"100%\"\n height={PLOT_HEIGHT}\n viewBox={`0 0 ${W} ${PLOT_HEIGHT}`}\n preserveAspectRatio=\"none\"\n style={{ display: \"block\" }}\n >\n <defs>\n <linearGradient id=\"ac-area-gradient\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stopColor=\"rgba(163, 205, 255, 0.4)\" />\n <stop offset=\"100%\" stopColor=\"rgba(163, 205, 255, 0)\" />\n </linearGradient>\n </defs>\n <polygon points={areaPoints} fill=\"url(#ac-area-gradient)\" />\n <polyline\n points={linePoints}\n fill=\"none\"\n stroke={AREA_LINE}\n strokeWidth={2.5}\n vectorEffect=\"non-scaling-stroke\"\n />\n </svg>\n </div>\n </div>\n <div className=\"chart-x-axis\">\n {xLabels.map((label) => (\n <span key={label}>{label}</span>\n ))}\n </div>\n </StyledChartWidget>\n );\n};\n\nAreaChartWidget.displayName = \"AreaChartWidget\";\n\n/* ------------------------------------------------------------------ */\n/* Daily +/- bars (mirrors DailyCreatedAndCompletedTasksWidget.js) */\n/* ------------------------------------------------------------------ */\n\n/** Bar colours from the real widget: new above, completed below. */\nconst DELTA_UP = \"#A3CDFF\";\nconst DELTA_DOWN = \"#FF9C9C\";\n\nexport interface DailyDeltaPoint {\n /** Count above the axis (new tasks). */\n up: number;\n /** Count below the axis (completed tasks). */\n down: number;\n}\n\nexport interface DailyDeltaChartWidgetProps {\n title: string;\n linkText?: string;\n data: DailyDeltaPoint[];\n /** X labels, spread evenly under the plot (pass a subset). */\n xLabels: string[];\n /** Scale above the axis. */\n upMax: number;\n /** Scale below the axis (can differ — the axis sits off-centre). */\n downMax: number;\n /** Tick values above the axis (0 and below-axis ticks are derived). */\n yTicksUp: number[];\n /** Tick values below the axis. */\n yTicksDown: number[];\n}\n\nconst StyledDeltaBars = styled.div`\n display: flex;\n height: 100%;\n\n .delta-col {\n position: relative;\n flex: 1;\n min-width: 0;\n }\n\n .delta-bar {\n position: absolute;\n left: 50%;\n width: 4px;\n max-width: 80%;\n transform: translateX(-50%);\n }\n\n .delta-zero {\n position: absolute;\n left: 0;\n right: 0;\n height: 1px;\n background-color: ${TICK_COLOR};\n }\n`;\n\n/** Thin daily bars above/below a zero line, like \"New vs Completed Tasks\". */\nexport const DailyDeltaChartWidget = ({\n title,\n linkText,\n data,\n xLabels,\n upMax,\n downMax,\n yTicksUp,\n yTicksDown,\n}: DailyDeltaChartWidgetProps): ReactElement => {\n const upFrac = upMax / (upMax + downMax);\n const zeroTop = upFrac * PLOT_HEIGHT;\n\n const tickTop = (value: number, below: boolean): number =>\n below\n ? zeroTop + (value / downMax) * (PLOT_HEIGHT - zeroTop)\n : zeroTop - (value / upMax) * zeroTop;\n\n return (\n <StyledChartWidget>\n <ChartHead title={title} linkText={linkText} />\n <div className=\"chart-row\">\n <div className=\"chart-y-axis\">\n {yTicksUp.map((tick) => (\n <span\n key={`up-${tick}`}\n className=\"chart-y-tick\"\n style={{ top: `${tickTop(tick, false)}px` }}\n >\n {tick}\n </span>\n ))}\n <span className=\"chart-y-tick\" style={{ top: `${zeroTop}px` }}>\n 0\n </span>\n {yTicksDown.map((tick) => (\n <span\n key={`down-${tick}`}\n className=\"chart-y-tick\"\n style={{ top: `${tickTop(tick, true)}px` }}\n >\n {tick}\n </span>\n ))}\n </div>\n <div className=\"chart-plot\">\n <StyledDeltaBars>\n <span className=\"delta-zero\" style={{ top: `${zeroTop}px` }} />\n {data.map((point, index) => (\n <span className=\"delta-col\" key={index}>\n {point.up > 0 ? (\n <span\n className=\"delta-bar\"\n style={{\n backgroundColor: DELTA_UP,\n bottom: `${PLOT_HEIGHT - zeroTop}px`,\n height: `${(point.up / upMax) * zeroTop}px`,\n }}\n />\n ) : null}\n {point.down > 0 ? (\n <span\n className=\"delta-bar\"\n style={{\n backgroundColor: DELTA_DOWN,\n top: `${zeroTop + 1}px`,\n height: `${\n (point.down / downMax) * (PLOT_HEIGHT - zeroTop)\n }px`,\n }}\n />\n ) : null}\n </span>\n ))}\n </StyledDeltaBars>\n </div>\n </div>\n <div className=\"chart-x-axis\">\n {xLabels.map((label) => (\n <span key={label}>{label}</span>\n ))}\n </div>\n </StyledChartWidget>\n );\n};\n\nDailyDeltaChartWidget.displayName = \"DailyDeltaChartWidget\";\n\n/* ------------------------------------------------------------------ */\n/* Leaderboard (mirrors LeaderboardWidget.js) */\n/* ------------------------------------------------------------------ */\n\nexport interface LeaderboardRowData {\n label: string;\n /** Preformatted value on the right (\"25:00\"). */\n value: string;\n /** Bar length as % of the longest row (100 for the leader). */\n percentOfMax: number;\n /** Billable share 0–100 — fills the green part of the bar. */\n billableShare: number;\n}\n\nexport interface LeaderboardWidgetProps {\n title: string;\n description: string;\n rows: LeaderboardRowData[];\n groupBy?: WidgetGroupByProps;\n}\n\nconst StyledLeaderboard = styled.div`\n position: relative;\n height: 100%;\n padding: 16px 20px;\n box-sizing: border-box;\n overflow: hidden;\n\n .lb-head {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n }\n\n .lb-desc {\n margin-bottom: 12px;\n }\n\n .lb-sep {\n border-bottom: 1px solid var(--border-primary);\n margin-bottom: 12px;\n }\n\n .lb-rows {\n max-height: 288px;\n overflow-y: auto;\n }\n\n .lb-row {\n display: flex;\n align-items: center;\n gap: 16px;\n height: 32px;\n margin-bottom: 4px;\n }\n\n .lb-label {\n width: 208px;\n max-width: 40%;\n min-width: 0;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n cursor: pointer;\n }\n\n .lb-bar {\n flex: 1;\n min-width: 0;\n height: 8px;\n }\n\n .lb-bar-inner {\n min-width: 8px;\n height: 100%;\n border-radius: 4px;\n overflow: hidden;\n }\n\n .lb-value {\n width: 80px;\n flex-shrink: 0;\n text-align: right;\n }\n`;\n\n/** Ranked bars: label, billable/non-billable bar, value — like Time's\n * Leaderboard. Bar length = share of the leader; green = billable part. */\nexport const LeaderboardWidget = ({\n title,\n description,\n rows,\n groupBy,\n}: LeaderboardWidgetProps): ReactElement => (\n <StyledLeaderboard>\n <div className=\"lb-head\">\n <Header2>{title}</Header2>\n {groupBy ? <WidgetGroupBy {...groupBy} /> : null}\n </div>\n <Body2 color=\"tertiary\" className=\"lb-desc\">\n {description}\n </Body2>\n <div className=\"lb-sep\" />\n <div className=\"lb-rows\">\n {rows.map((row) => (\n <div className=\"lb-row\" key={row.label}>\n <span className=\"lb-label\">\n <Body2 color=\"theme-primary\">{row.label}</Body2>\n </span>\n <span className=\"lb-bar\">\n <span\n className=\"lb-bar-inner\"\n style={{ width: `${row.percentOfMax}%`, display: \"block\" }}\n >\n <ProgressBar\n progress={row.billableShare}\n stroke={8}\n progressColor={colors.greenSuccess.color}\n />\n </span>\n </span>\n <span className=\"lb-value\">\n <Body2 color=\"secondary\">{row.value}</Body2>\n </span>\n </div>\n ))}\n </div>\n </StyledLeaderboard>\n);\n\nLeaderboardWidget.displayName = \"LeaderboardWidget\";\n\n/* ------------------------------------------------------------------ */\n/* Stacked columns (mirrors TotalTrackedHoursChart.js bar mode) */\n/* ------------------------------------------------------------------ */\n\nexport interface StackedBarColumn {\n label: string;\n /** One value per series, bottom segment first (palette order). */\n segments: number[];\n}\n\nexport interface StackedBarChartWidgetProps {\n title?: string;\n /** Preformatted big total shown top-right (\"318:11\"). */\n total?: string;\n data: StackedBarColumn[];\n /** Series names for the segment tooltips, palette order. */\n seriesLabels: string[];\n /** Y tick values; the max defines the scale. */\n yTicks: number[];\n /** Column width in px — the real charts are narrow (default 28). */\n barWidth?: number;\n /** Plot height in px (default 220 — this widget is usually taller). */\n height?: number;\n groupBy?: WidgetGroupByProps;\n}\n\nconst StyledStackedChart = styled.div`\n position: relative;\n height: 100%;\n padding: 16px 20px;\n box-sizing: border-box;\n overflow: hidden;\n\n .sb-head {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n gap: 8px;\n margin-bottom: 8px;\n }\n\n .sb-total-wrap {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n margin-left: auto;\n }\n\n .sb-total {\n font-family: ${FONT_STACK};\n font-size: 52px;\n font-weight: 700;\n line-height: 1;\n color: var(--color-theme-900);\n }\n\n .sb-row {\n display: flex;\n gap: 10px;\n }\n\n .sb-y-axis {\n position: relative;\n width: 30px;\n flex-shrink: 0;\n }\n\n .sb-y-tick {\n position: absolute;\n right: 0;\n transform: translateY(-50%);\n font-family: ${FONT_STACK};\n font-size: 11px;\n color: ${TICK_COLOR};\n }\n\n .sb-plot {\n position: relative;\n flex: 1;\n min-width: 0;\n }\n\n .sb-grid-line {\n position: absolute;\n left: 0;\n right: 0;\n height: 1px;\n background-color: var(--color-theme-300);\n }\n\n .sb-cols {\n position: relative;\n display: flex;\n justify-content: space-around;\n align-items: flex-end;\n height: 100%;\n }\n\n .sb-slot {\n display: flex;\n flex-direction: column-reverse;\n flex-shrink: 0;\n }\n\n .sb-labels {\n display: flex;\n justify-content: space-around;\n margin-top: 8px;\n padding-left: 40px;\n font-family: ${FONT_STACK};\n font-size: 11px;\n color: ${TICK_COLOR};\n }\n`;\n\n/** Narrow stacked time columns, like the Time dashboard's tracked-hours\n * chart. Segment order and palette follow the real chart. */\nexport const StackedBarChartWidget = ({\n title,\n total,\n data,\n seriesLabels,\n yTicks,\n barWidth = 28,\n height = 220,\n groupBy,\n}: StackedBarChartWidgetProps): ReactElement => {\n const max = Math.max(...yTicks) || 1;\n return (\n <StyledStackedChart>\n <div className=\"sb-head\">\n {title ? <Body1 weight=\"bold\">{title}</Body1> : null}\n <span className=\"sb-total-wrap\">\n {total ? <span className=\"sb-total\">{total}</span> : null}\n {groupBy ? <WidgetGroupBy {...groupBy} /> : null}\n </span>\n </div>\n <div className=\"sb-row\">\n <div className=\"sb-y-axis\" style={{ height: `${height}px` }}>\n {yTicks.map((tick) => (\n <span\n key={tick}\n className=\"sb-y-tick\"\n style={{ top: `${((max - tick) / max) * height}px` }}\n >\n {tick}\n </span>\n ))}\n </div>\n <div className=\"sb-plot\" style={{ height: `${height}px` }}>\n {yTicks.map((tick) => (\n <span\n key={tick}\n className=\"sb-grid-line\"\n style={{ top: `${((max - tick) / max) * height}px` }}\n />\n ))}\n <div className=\"sb-cols\">\n {data.map((column) => (\n <div\n className=\"sb-slot\"\n key={column.label}\n style={{ width: `${barWidth}px` }}\n >\n {column.segments.map((value, index) =>\n value > 0 ? (\n <Tooltip\n key={seriesLabels[index] ?? index}\n title={`${seriesLabels[index]}: ${value}h`}\n >\n <span\n style={{\n display: \"block\",\n height: `${(value / max) * height}px`,\n backgroundColor:\n CHART_SERIES_COLORS[\n index % CHART_SERIES_COLORS.length\n ],\n }}\n />\n </Tooltip>\n ) : null\n )}\n </div>\n ))}\n </div>\n </div>\n </div>\n <div className=\"sb-labels\">\n {data.map((column) => (\n <span key={column.label}>{column.label}</span>\n ))}\n </div>\n </StyledStackedChart>\n );\n};\n\nStackedBarChartWidget.displayName = \"StackedBarChartWidget\";\n"],"mappings":"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","ignoreList":[]}
@@ -9,17 +9,6 @@ export declare const PageHeader: {
9
9
  ({ title, children, }: PageHeaderProps): ReactElement;
10
10
  displayName: string;
11
11
  };
12
- export interface ProjectOptionsMenuProps {
13
- /** When the `source` module is loaded, show the Repositories section. */
14
- sourceModuleLoaded?: boolean;
15
- /** Repositories already connected to the project when the menu first mounts. */
16
- initialConnectedRepositories?: Repository[];
17
- /**
18
- * Whether the current user can manage the project's repositories. Gates the
19
- * Webhook Logs entry (a manage-only action) — see note 09, Permissions.
20
- */
21
- canManageProjectRepositories?: boolean;
22
- }
23
12
  export interface ProjectPageHeaderProps {
24
13
  title?: string;
25
14
  /** When the `source` module is loaded, the "..." menu shows a Repositories
@@ -1 +1 @@
1
- {"version":3,"file":"headers.d.ts","sourceRoot":"","sources":["../../../../src/presentation/shared/headers.tsx"],"names":[],"mappings":"AAAA,OAAc,EAEZ,YAAY,EACZ,SAAS,EAGV,MAAM,OAAO,CAAC;AAIf,OAAO,EAGL,UAAU,EACX,MAAM,2BAA2B,CAAC;AA+InC,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED,+EAA+E;AAC/E,eAAO,MAAM,UAAU;2BAGpB,eAAe,GAAG,YAAY;;CAShC,CAAC;AAyJF,MAAM,WAAW,uBAAuB;IACtC,yEAAyE;IACzE,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,gFAAgF;IAChF,4BAA4B,CAAC,EAAE,UAAU,EAAE,CAAC;IAC5C;;;OAGG;IACH,4BAA4B,CAAC,EAAE,OAAO,CAAC;CACxC;AA2eD,MAAM,WAAW,sBAAsB;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;iEAC6D;IAC7D,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,iFAAiF;IACjF,4BAA4B,CAAC,EAAE,UAAU,EAAE,CAAC;IAC5C,sEAAsE;IACtE,4BAA4B,CAAC,EAAE,OAAO,CAAC;CACxC;AAED,mFAAmF;AACnF,eAAO,MAAM,iBAAiB;iGAK3B,sBAAsB,GAAG,YAAY;;CAkCvC,CAAC;AAsCF,MAAM,WAAW,cAAc;IAC7B,uDAAuD;IACvD,UAAU,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,UAAU,CAAC;CAC7C;AAED,wEAAwE;AACxE,eAAO,MAAM,SAAS;sBAEnB,cAAc,GAAG,YAAY;;CA8C/B,CAAC"}
1
+ {"version":3,"file":"headers.d.ts","sourceRoot":"","sources":["../../../../src/presentation/shared/headers.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAE,YAAY,EAAE,SAAS,EAAY,MAAM,OAAO,CAAC;AAIjE,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AA8GvD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED,+EAA+E;AAC/E,eAAO,MAAM,UAAU;2BAGpB,eAAe,GAAG,YAAY;;CAShC,CAAC;AAmMF,MAAM,WAAW,sBAAsB;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;iEAC6D;IAC7D,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,iFAAiF;IACjF,4BAA4B,CAAC,EAAE,UAAU,EAAE,CAAC;IAC5C,sEAAsE;IACtE,4BAA4B,CAAC,EAAE,OAAO,CAAC;CACxC;AAED,mFAAmF;AACnF,eAAO,MAAM,iBAAiB;iGAK3B,sBAAsB,GAAG,YAAY;;CAkCvC,CAAC;AAsCF,MAAM,WAAW,cAAc;IAC7B,uDAAuD;IACvD,UAAU,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,UAAU,CAAC;CAC7C;AAED,wEAAwE;AACxE,eAAO,MAAM,SAAS;sBAEnB,cAAc,GAAG,YAAY;;CA8C/B,CAAC"}
@@ -1,25 +1,18 @@
1
- import React, { useCallback, useState } from "react";
2
- import styled, { createGlobalStyle } from "styled-components";
3
- import { ConnectRepositoryDialog } from "./ConnectRepositoryDialog";
1
+ import React, { useState } from "react";
2
+ import styled from "styled-components";
3
+ import { ProjectOptionsMenu } from "./ProjectOptionsMenu";
4
4
  import { RoundAvatar } from "./RoundAvatar";
5
5
  import { AVATAR_COLORS, MD, SM, TRANSITION } from "./tokens";
6
- import { WEBHOOK_CONNECTIONS, WEBHOOK_REPOSITORIES, WebhookLogsDialog } from "./WebhookLogsDialog";
7
- import { Badge } from "../../components/Badge";
8
6
  import { Button } from "../../components/Button";
9
7
  import { GlobalAddButton } from "../../components/Button/GlobalAddButton";
10
- import { CompleteCheckbox } from "../../components/CompleteCheckbox";
11
8
  import { CounterButton } from "../../components/CounterButton";
12
- import { Dialog } from "../../components/Dialog";
13
9
  import { Header } from "../../components/Header";
14
10
  import { IconButton } from "../../components/IconButton";
15
- import { AccessLogIcon, AddCrossTinyIcon, ArrowLeftIcon, CaretRightIcon, CheckboxBlankTogglerIcon, CloseSmallIcon, CrownBlankIcon, CrownSelectedIcon, DownloadIcon, DuplicateIcon, EditIcon, EditMultipleIcon, FilterIcon, GitHubIcon, GitIcon, GitLabIcon, GitRepositoryConnectIcon, GitRepositoryIcon, InfoIcon, InsertLinkIcon, LabelsIcon, NotificationBellIcon, PeopleIcon, ProjectTemplateConvertIcon, ProjectTemplateIcon, StarIcon, TrashIcon, TreeDotsIcon, ViewListIcon, ViewTimelineIcon } from "../../components/Icons";
16
- import { List, ListItem, ListSeparator } from "../../components/List";
11
+ import { AddCrossTinyIcon, ArrowLeftIcon, CloseSmallIcon, CrownBlankIcon, CrownSelectedIcon, EditMultipleIcon, FilterIcon, InfoIcon, PeopleIcon, ViewListIcon, ViewTimelineIcon } from "../../components/Icons";
17
12
  import { Menu, MenuHeader } from "../../components/Menu";
18
13
  import { Item, Nav } from "../../components/Nav";
19
14
  import { ProgressPie } from "../../components/ProgressPie";
20
- import { ToastMessage } from "../../components/ToastMessage";
21
15
  import { Tooltip } from "../../components/Tooltip";
22
- import { ResizeTransition, SlideFromTop, SlideLeftRightTransition } from "../../components/Transitions";
23
16
  import { Body2, Caption1, Header2, Title2 } from "../../components/Typography";
24
17
 
25
18
  /** Gold used for the project-leader cues (a data colour, not a theme token). */
@@ -60,291 +53,6 @@ const StyledProjectHeaderChildren = styled.div.withConfig({
60
53
  componentId: "sc-yf6o6n-1"
61
54
  })(["display:flex;align-items:center;gap:8px;.project-progress{display:flex;align-items:center;margin-left:4px;}"]);
62
55
 
63
- /* Project "..." options menu (Menu + List with leading-icon items). Two items
64
- (Favorite, Subscribe) have a checkbox on the right. Clicks are no-ops. */
65
- const StyledProjectMenu = styled.div.withConfig({
66
- displayName: "headers__StyledProjectMenu",
67
- componentId: "sc-yf6o6n-2"
68
- })([".toggle-item{justify-content:space-between;}.toggle-item .opt-left{display:flex;align-items:center;min-width:0;}.toggle-item .opt-left svg{margin-right:8px;flex-shrink:0;}.toggle-item .c-complete-checkbox{width:16px;height:16px;border-radius:3px;align-self:center;flex-shrink:0;}.submenu-item{justify-content:space-between;}.submenu-item .repo-right{display:flex;align-items:center;gap:8px;flex-shrink:0;}.submenu-item .repo-right .c-badge{background-color:var(--color-theme-300);color:var(--color-theme-700);}.submenu-item .repo-caret{flex-shrink:0;fill:var(--color-theme-600);}.repo-row{min-width:0;}.repo-row > svg{flex-shrink:0;}.repo-name{min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}"]);
69
-
70
- /* The project "..." menu shares the Webhook Logs dialog's repository /
71
- * connection universe, so a repository connected here is one that dialog can
72
- * pre-filter by. `WebhookConnection` and `Connection` share a shape, and a
73
- * `WebhookRepository`'s `path` maps onto a `Repository`'s `name`. */
74
- const PROJECT_MENU_CONNECTIONS = WEBHOOK_CONNECTIONS;
75
- const PROJECT_MENU_REPOSITORIES = WEBHOOK_REPOSITORIES.map(repo => ({
76
- id: repo.id,
77
- name: repo.path,
78
- connectionId: repo.connectionId
79
- }));
80
-
81
- /** Submenu row label for a connected repository: "path (Connection)". The
82
- * service type is omitted because the leading provider icon already conveys
83
- * it. */
84
- const repositoryMenuLabel = repo => {
85
- const connection = PROJECT_MENU_CONNECTIONS.find(c => c.id === repo.connectionId);
86
- return connection ? repo.name + " (" + connection.name + ")" : repo.name;
87
- };
88
-
89
- /** Provider glyph for a connected repository: GitHub / GitLab for those
90
- * services, and the generic Git mark for anything else (e.g. an upcoming
91
- * Bitbucket connection). */
92
- const repositoryIcon = repo => {
93
- const connection = PROJECT_MENU_CONNECTIONS.find(c => c.id === repo.connectionId);
94
- switch (connection == null ? void 0 : connection.service) {
95
- case "github":
96
- return GitHubIcon;
97
- case "gitlab":
98
- return GitLabIcon;
99
- default:
100
- return GitIcon;
101
- }
102
- };
103
-
104
- /** Width of the project "..." menu (matches the DS "normal" menu mode). */
105
- const PROJECT_MENU_WIDTH = 260;
106
-
107
- /* The menu drills in place (index → Repositories), so the paper must clip the
108
- sliding panels and give them a positioning context. */
109
- const ProjectMenuSliderStyle = createGlobalStyle([".c-simple-menu__paper.project-options-menu{overflow:hidden;position:relative;}"]);
110
-
111
- /* Toast anchor — fixed, upper-right corner (the toast slides down from the
112
- top). The wrapper ignores pointer events so it never blocks the page; only
113
- the toast itself is interactive. */
114
- const StyledToastAnchor = styled.div.withConfig({
115
- displayName: "headers__StyledToastAnchor",
116
- componentId: "sc-yf6o6n-3"
117
- })(["position:fixed;top:16px;right:16px;z-index:10000;pointer-events:none;.c-toast-message{pointer-events:auto;}"]);
118
- /**
119
- * The project "..." options menu. When the `source` module is loaded it gains
120
- * a **Repositories** item that, instead of flying out to the side, **drills in
121
- * within the same menu** (the pattern used across the app — see `Filter`): the
122
- * index slides out to the left and the Repositories view (a back-arrow header,
123
- * the connected repositories sorted by name, and a **Connect Repository**
124
- * action) slides in. Connecting adds a repository to the list; clicking one
125
- * would, in production, open it in a new tab (surfaced here via a dialog).
126
- */
127
- const ProjectOptionsMenu = _ref2 => {
128
- let _ref2$sourceModuleLoa = _ref2.sourceModuleLoaded,
129
- sourceModuleLoaded = _ref2$sourceModuleLoa === void 0 ? false : _ref2$sourceModuleLoa,
130
- _ref2$initialConnecte = _ref2.initialConnectedRepositories,
131
- initialConnectedRepositories = _ref2$initialConnecte === void 0 ? [] : _ref2$initialConnecte,
132
- _ref2$canManageProjec = _ref2.canManageProjectRepositories,
133
- canManageProjectRepositories = _ref2$canManageProjec === void 0 ? true : _ref2$canManageProjec;
134
- const _useState = useState(false),
135
- open = _useState[0],
136
- setOpen = _useState[1];
137
- const _useState2 = useState("index"),
138
- view = _useState2[0],
139
- setView = _useState2[1];
140
- const _useState3 = useState(false),
141
- webhookLogsOpen = _useState3[0],
142
- setWebhookLogsOpen = _useState3[1];
143
- const _useState4 = useState(true),
144
- isLeft = _useState4[0],
145
- setIsLeft = _useState4[1];
146
- const _useState5 = useState(0),
147
- height = _useState5[0],
148
- setHeight = _useState5[1];
149
- // Connected repositories drive the count badge on the Repositories item. In
150
- // production this count comes from the project's `count_repositories` counter,
151
- // kept current via pusher/websocket events, so the badge reflects repositories
152
- // connected or disconnected by anyone — not just the current user's actions.
153
- const _useState6 = useState(initialConnectedRepositories),
154
- connectedRepos = _useState6[0],
155
- setConnectedRepos = _useState6[1];
156
- const _useState7 = useState(false),
157
- connectOpen = _useState7[0],
158
- setConnectOpen = _useState7[1];
159
- const _useState8 = useState(false),
160
- infoOpen = _useState8[0],
161
- setInfoOpen = _useState8[1];
162
- const _useState9 = useState(false),
163
- toastOpen = _useState9[0],
164
- setToastOpen = _useState9[1];
165
- // Bumped on each connect so the toast remounts and its auto-hide timer
166
- // restarts from the moment it is shown.
167
- const _useState0 = useState(0),
168
- toastKey = _useState0[0],
169
- setToastKey = _useState0[1];
170
-
171
- // Repositories still available to connect (not already on the project).
172
- const connectableRepos = PROJECT_MENU_REPOSITORIES.filter(r => !connectedRepos.some(c => c.id === r.id));
173
-
174
- // Connected repositories are listed in the submenu sorted by name.
175
- const sortedRepos = [...connectedRepos].sort((a, b) => a.name.localeCompare(b.name));
176
-
177
- // Each view measures itself as it mounts so the paper can animate its height.
178
- const measure = useCallback(node => {
179
- if (node) {
180
- setHeight(node.offsetHeight);
181
- }
182
- }, []);
183
- const goToRepositories = () => {
184
- setView("repositories");
185
- setIsLeft(true);
186
- };
187
- const backToIndex = () => {
188
- setView("index");
189
- setIsLeft(false);
190
- };
191
- const handleClose = () => {
192
- setOpen(false);
193
- // Reset to the index so the next open starts at the top level.
194
- setView("index");
195
- setIsLeft(true);
196
- };
197
- const handleConnected = repo => {
198
- setConnectedRepos(prev => prev.some(r => r.id === repo.id) ? prev : [...prev, repo]);
199
- setToastOpen(true);
200
- setToastKey(k => k + 1);
201
- };
202
- const handleConnect = () => {
203
- handleClose();
204
- setConnectOpen(true);
205
- };
206
-
207
- // In production this closes the menu and opens the repository in a new tab;
208
- // in the mock we surface that behaviour in a small dialog instead.
209
- const handleOpenRepository = () => {
210
- handleClose();
211
- setInfoOpen(true);
212
- };
213
- const handleOpenWebhookLogs = () => {
214
- handleClose();
215
- setWebhookLogsOpen(true);
216
- };
217
- const indexView = /*#__PURE__*/React.createElement(StyledProjectMenu, null, /*#__PURE__*/React.createElement(List, {
218
- style: {
219
- padding: "8px 0"
220
- },
221
- tabIndex: -1
222
- }, /*#__PURE__*/React.createElement(ListItem, null, /*#__PURE__*/React.createElement(EditIcon, null), "Edit"), /*#__PURE__*/React.createElement(ListItem, {
223
- className: "toggle-item"
224
- }, /*#__PURE__*/React.createElement("span", {
225
- className: "opt-left"
226
- }, /*#__PURE__*/React.createElement(StarIcon, null), "Mark as Favorite"), /*#__PURE__*/React.createElement(CompleteCheckbox, {
227
- primary: true,
228
- completed: true
229
- })), /*#__PURE__*/React.createElement(ListItem, {
230
- className: "toggle-item"
231
- }, /*#__PURE__*/React.createElement("span", {
232
- className: "opt-left"
233
- }, /*#__PURE__*/React.createElement(NotificationBellIcon, null), "Subscribe to Everything"), /*#__PURE__*/React.createElement(CompleteCheckbox, {
234
- primary: true,
235
- completed: false
236
- })), /*#__PURE__*/React.createElement(ListItem, null, /*#__PURE__*/React.createElement(LabelsIcon, null), "Manage Task Labels"), /*#__PURE__*/React.createElement(ListItem, null, /*#__PURE__*/React.createElement(InsertLinkIcon, null), "Copy Link"), /*#__PURE__*/React.createElement(ListSeparator, null), /*#__PURE__*/React.createElement(ListItem, null, /*#__PURE__*/React.createElement(CheckboxBlankTogglerIcon, null), "Complete"), /*#__PURE__*/React.createElement(ListItem, null, /*#__PURE__*/React.createElement(DownloadIcon, null), "Export"), sourceModuleLoaded ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ListSeparator, null), /*#__PURE__*/React.createElement(ListItem, {
237
- className: "toggle-item submenu-item",
238
- onClick: goToRepositories
239
- }, /*#__PURE__*/React.createElement("span", {
240
- className: "opt-left"
241
- }, /*#__PURE__*/React.createElement(GitRepositoryIcon, null), "Repositories"), /*#__PURE__*/React.createElement("span", {
242
- className: "repo-right"
243
- }, connectedRepos.length > 0 ? /*#__PURE__*/React.createElement(Badge, {
244
- isStandalone: true,
245
- dimension: 16,
246
- value: connectedRepos.length
247
- }) : null, /*#__PURE__*/React.createElement(CaretRightIcon, {
248
- className: "repo-caret",
249
- width: 16,
250
- height: 16
251
- })))) : null, /*#__PURE__*/React.createElement(ListSeparator, null), /*#__PURE__*/React.createElement(ListItem, null, /*#__PURE__*/React.createElement(DuplicateIcon, null), "Duplicate"), /*#__PURE__*/React.createElement(ListItem, null, /*#__PURE__*/React.createElement(ProjectTemplateIcon, null), "Apply Template"), /*#__PURE__*/React.createElement(ListItem, null, /*#__PURE__*/React.createElement(ProjectTemplateConvertIcon, null), "Convert to Template"), /*#__PURE__*/React.createElement(ListSeparator, null), /*#__PURE__*/React.createElement(ListItem, null, /*#__PURE__*/React.createElement(TrashIcon, null), "Delete")));
252
- return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ProjectMenuSliderStyle, null), /*#__PURE__*/React.createElement(Menu, {
253
- open: open,
254
- onOpen: () => setOpen(true),
255
- onClose: handleClose,
256
- position: "bottom-end",
257
- menuClassName: sourceModuleLoaded ? "project-options-menu" : undefined,
258
- target: /*#__PURE__*/React.createElement(IconButton, {
259
- type: "button",
260
- variant: "text gray",
261
- active: open
262
- }, /*#__PURE__*/React.createElement(TreeDotsIcon, null))
263
- }, sourceModuleLoaded ? /*#__PURE__*/React.createElement(ResizeTransition, {
264
- in: true,
265
- style: {
266
- height,
267
- width: PROJECT_MENU_WIDTH
268
- }
269
- }, /*#__PURE__*/React.createElement("div", {
270
- style: {
271
- position: "relative",
272
- overflow: "hidden"
273
- }
274
- }, /*#__PURE__*/React.createElement(SlideLeftRightTransition, {
275
- in: view === "index",
276
- direction: isLeft ? "left" : "right"
277
- }, /*#__PURE__*/React.createElement("div", {
278
- ref: measure,
279
- style: {
280
- width: PROJECT_MENU_WIDTH
281
- }
282
- }, indexView)), /*#__PURE__*/React.createElement(SlideLeftRightTransition, {
283
- in: view === "repositories",
284
- direction: isLeft ? "left" : "right"
285
- }, /*#__PURE__*/React.createElement("div", {
286
- ref: measure,
287
- style: {
288
- width: PROJECT_MENU_WIDTH
289
- }
290
- }, /*#__PURE__*/React.createElement(MenuHeader, {
291
- title: "Repositories",
292
- leftElement: /*#__PURE__*/React.createElement(IconButton, {
293
- type: "button",
294
- variant: "text gray",
295
- size: "small",
296
- onClick: backToIndex,
297
- "aria-label": "Back"
298
- }, /*#__PURE__*/React.createElement(ArrowLeftIcon, null))
299
- }), /*#__PURE__*/React.createElement(StyledProjectMenu, null, /*#__PURE__*/React.createElement(List, {
300
- style: {
301
- padding: "8px 0"
302
- },
303
- tabIndex: -1
304
- }, sortedRepos.map(repo => {
305
- const RepoIcon = repositoryIcon(repo);
306
- return /*#__PURE__*/React.createElement(ListItem, {
307
- key: repo.id,
308
- className: "repo-row",
309
- onClick: () => handleOpenRepository()
310
- }, /*#__PURE__*/React.createElement(RepoIcon, null), /*#__PURE__*/React.createElement("span", {
311
- className: "repo-name"
312
- }, repositoryMenuLabel(repo)));
313
- }), sortedRepos.length > 0 ? /*#__PURE__*/React.createElement(ListSeparator, null) : null, sortedRepos.length > 0 && canManageProjectRepositories ? /*#__PURE__*/React.createElement(ListItem, {
314
- onClick: handleOpenWebhookLogs
315
- }, /*#__PURE__*/React.createElement(AccessLogIcon, null), "Webhook Logs") : null, /*#__PURE__*/React.createElement(ListItem, {
316
- onClick: handleConnect
317
- }, /*#__PURE__*/React.createElement(GitRepositoryConnectIcon, null), "Connect Repository"))))))) : indexView), /*#__PURE__*/React.createElement(ConnectRepositoryDialog, {
318
- open: connectOpen,
319
- onClose: () => setConnectOpen(false),
320
- onConnect: handleConnected,
321
- repositories: connectableRepos,
322
- connections: PROJECT_MENU_CONNECTIONS
323
- }), /*#__PURE__*/React.createElement(WebhookLogsDialog, {
324
- open: webhookLogsOpen,
325
- onClose: () => setWebhookLogsOpen(false),
326
- repositoryIds: sortedRepos.map(repo => repo.id)
327
- }), /*#__PURE__*/React.createElement(Dialog, {
328
- open: infoOpen,
329
- onClose: () => setInfoOpen(false),
330
- enableBackgroundClick: true
331
- }, /*#__PURE__*/React.createElement(Dialog.Title, null, "Open Repository"), /*#__PURE__*/React.createElement(Dialog.ContentDivider, null), /*#__PURE__*/React.createElement(Dialog.Content, null, /*#__PURE__*/React.createElement(Body2, null, "In production, this click would close the menu and open the repository in a new browser tab.")), /*#__PURE__*/React.createElement(Dialog.ContentDivider, null), /*#__PURE__*/React.createElement(Dialog.Actions, null, /*#__PURE__*/React.createElement(Button, {
332
- variant: "primary",
333
- onClick: () => setInfoOpen(false)
334
- }, "Got it"))), /*#__PURE__*/React.createElement(StyledToastAnchor, null, /*#__PURE__*/React.createElement(SlideFromTop, {
335
- in: toastOpen
336
- }, /*#__PURE__*/React.createElement(ToastMessage, {
337
- key: toastKey,
338
- className: "c-toast-message",
339
- type: "success",
340
- text: "Repository connected.",
341
- dismissible: true,
342
- dropShadow: true,
343
- timeout: 3000,
344
- onClose: () => setToastOpen(false)
345
- }))));
346
- };
347
-
348
56
  /* People popover (mirrors the project header People dropdown): a header row
349
57
  ("People" + add button), a "Members" section and a row per member. The
350
58
  project leader shows a gold crown; other members reveal a "set as leader"
@@ -370,12 +78,12 @@ const PROJECT_MEMBERS = [{
370
78
  }];
371
79
  const StyledPeopleMenu = styled.div.withConfig({
372
80
  displayName: "headers__StyledPeopleMenu",
373
- componentId: "sc-yf6o6n-4"
81
+ componentId: "sc-yf6o6n-2"
374
82
  })(["width:256px;.members-label{display:block;margin:8px 0;padding:0 16px;}.member-row{position:relative;display:flex;align-items:center;min-height:40px;margin:0 8px;padding:2px 8px;border-radius:4px;cursor:default;transition:background-color ", ";}.member-row:hover{background-color:var(--color-theme-200);}.member-row.leader::before{content:\"\";position:absolute;top:4px;bottom:4px;left:0;width:4px;border-radius:4px;background-color:", ";}.member-row.leader .member-avatar{outline:2px solid ", ";outline-offset:-2px;}.member-name{flex:1;margin-left:12px;min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}.member-right{display:flex;align-items:center;gap:2px;flex-shrink:0;margin-left:8px;}.leader-crown{flex-shrink:0;}.member-options{display:none;align-items:center;gap:2px;}.member-row:hover .member-options{display:flex;}"], TRANSITION, LEADER_GOLD, LEADER_GOLD);
375
83
  const PeoplePopover = () => {
376
- const _useState1 = useState(false),
377
- open = _useState1[0],
378
- setOpen = _useState1[1];
84
+ const _useState = useState(false),
85
+ open = _useState[0],
86
+ setOpen = _useState[1];
379
87
  return /*#__PURE__*/React.createElement(Menu, {
380
88
  open: open,
381
89
  onOpen: () => setOpen(true),
@@ -431,13 +139,13 @@ const PeoplePopover = () => {
431
139
  }, /*#__PURE__*/React.createElement(CloseSmallIcon, null)))))))));
432
140
  };
433
141
  /** The project page header: back arrow, title, progress, info, people, options. */
434
- export const ProjectPageHeader = _ref3 => {
435
- let _ref3$title = _ref3.title,
436
- title = _ref3$title === void 0 ? "#131: Ime projekta" : _ref3$title,
437
- _ref3$sourceModuleLoa = _ref3.sourceModuleLoaded,
438
- sourceModuleLoaded = _ref3$sourceModuleLoa === void 0 ? false : _ref3$sourceModuleLoa,
439
- initialConnectedRepositories = _ref3.initialConnectedRepositories,
440
- canManageProjectRepositories = _ref3.canManageProjectRepositories;
142
+ export const ProjectPageHeader = _ref2 => {
143
+ let _ref2$title = _ref2.title,
144
+ title = _ref2$title === void 0 ? "#131: Ime projekta" : _ref2$title,
145
+ _ref2$sourceModuleLoa = _ref2.sourceModuleLoaded,
146
+ sourceModuleLoaded = _ref2$sourceModuleLoa === void 0 ? false : _ref2$sourceModuleLoa,
147
+ initialConnectedRepositories = _ref2.initialConnectedRepositories,
148
+ canManageProjectRepositories = _ref2.canManageProjectRepositories;
441
149
  return /*#__PURE__*/React.createElement(StyledPageHeader, null, /*#__PURE__*/React.createElement("div", {
442
150
  className: "page-header-left"
443
151
  }, /*#__PURE__*/React.createElement(IconButton, {
@@ -477,19 +185,19 @@ ProjectPageHeader.displayName = "ProjectPageHeader";
477
185
  const NAV_TABS = ["Tasks", "Discussions", "Files", "Notes", "Activity"];
478
186
  const StyledTabHeader = styled(Header).withConfig({
479
187
  displayName: "headers__StyledTabHeader",
480
- componentId: "sc-yf6o6n-5"
188
+ componentId: "sc-yf6o6n-3"
481
189
  })(["justify-content:space-between;align-items:center;margin-bottom:16px;min-height:64px;flex-shrink:0;"]);
482
190
  const StyledTabControls = styled.div.withConfig({
483
191
  displayName: "headers__StyledTabControls",
484
- componentId: "sc-yf6o6n-6"
192
+ componentId: "sc-yf6o6n-4"
485
193
  })(["display:flex;align-items:center;flex-shrink:0;gap:4px;.vertical-separator{width:1px;height:24px;background-color:var(--color-theme-400);margin:0 8px;}.filter-button{display:flex;align-items:center;gap:6px;}"]);
486
194
  /** The Tasks/Discussions/… tab bar plus the right-hand view toolbar. */
487
- export const TabHeader = _ref4 => {
488
- let _ref4$activeView = _ref4.activeView,
489
- activeView = _ref4$activeView === void 0 ? "list" : _ref4$activeView;
490
- const _useState10 = useState(0),
491
- active = _useState10[0],
492
- setActive = _useState10[1];
195
+ export const TabHeader = _ref3 => {
196
+ let _ref3$activeView = _ref3.activeView,
197
+ activeView = _ref3$activeView === void 0 ? "list" : _ref3$activeView;
198
+ const _useState2 = useState(0),
199
+ active = _useState2[0],
200
+ setActive = _useState2[1];
493
201
  return /*#__PURE__*/React.createElement(StyledTabHeader, null, /*#__PURE__*/React.createElement(Nav, {
494
202
  onSelect: setActive
495
203
  }, NAV_TABS.map((label, index) => /*#__PURE__*/React.createElement(Item, {