@flagsmith/backstage-plugin 0.1.0-pr.7.3135fb9

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 (60) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +163 -0
  3. package/dist/api/FlagsmithClient.esm.js +149 -0
  4. package/dist/api/FlagsmithClient.esm.js.map +1 -0
  5. package/dist/components/FlagsTab/EnvironmentTable.esm.js +124 -0
  6. package/dist/components/FlagsTab/EnvironmentTable.esm.js.map +1 -0
  7. package/dist/components/FlagsTab/ExpandableRow.esm.js +218 -0
  8. package/dist/components/FlagsTab/ExpandableRow.esm.js.map +1 -0
  9. package/dist/components/FlagsTab/FeatureAnalyticsSection.esm.js +178 -0
  10. package/dist/components/FlagsTab/FeatureAnalyticsSection.esm.js.map +1 -0
  11. package/dist/components/FlagsTab/FeatureDetailsGrid.esm.js +160 -0
  12. package/dist/components/FlagsTab/FeatureDetailsGrid.esm.js.map +1 -0
  13. package/dist/components/FlagsTab/SegmentOverridesSection.esm.js +129 -0
  14. package/dist/components/FlagsTab/SegmentOverridesSection.esm.js.map +1 -0
  15. package/dist/components/FlagsTab/index.esm.js +138 -0
  16. package/dist/components/FlagsTab/index.esm.js.map +1 -0
  17. package/dist/components/FlagsmithOverviewCard/FeatureFlagRow.esm.js +41 -0
  18. package/dist/components/FlagsmithOverviewCard/FeatureFlagRow.esm.js.map +1 -0
  19. package/dist/components/FlagsmithOverviewCard/FlagStatsRow.esm.js +46 -0
  20. package/dist/components/FlagsmithOverviewCard/FlagStatsRow.esm.js.map +1 -0
  21. package/dist/components/FlagsmithOverviewCard/index.esm.js +90 -0
  22. package/dist/components/FlagsmithOverviewCard/index.esm.js.map +1 -0
  23. package/dist/components/FlagsmithUsageCard/UsageChart.esm.js +84 -0
  24. package/dist/components/FlagsmithUsageCard/UsageChart.esm.js.map +1 -0
  25. package/dist/components/FlagsmithUsageCard/index.esm.js +62 -0
  26. package/dist/components/FlagsmithUsageCard/index.esm.js.map +1 -0
  27. package/dist/components/shared/ChartTooltip.esm.js +33 -0
  28. package/dist/components/shared/ChartTooltip.esm.js.map +1 -0
  29. package/dist/components/shared/ErrorState.esm.js +13 -0
  30. package/dist/components/shared/ErrorState.esm.js.map +1 -0
  31. package/dist/components/shared/FlagStatusIndicator.esm.js +61 -0
  32. package/dist/components/shared/FlagStatusIndicator.esm.js.map +1 -0
  33. package/dist/components/shared/FlagsmithLink.esm.js +74 -0
  34. package/dist/components/shared/FlagsmithLink.esm.js.map +1 -0
  35. package/dist/components/shared/LoadingState.esm.js +35 -0
  36. package/dist/components/shared/LoadingState.esm.js.map +1 -0
  37. package/dist/components/shared/MiniPagination.esm.js +66 -0
  38. package/dist/components/shared/MiniPagination.esm.js.map +1 -0
  39. package/dist/components/shared/SearchInput.esm.js +54 -0
  40. package/dist/components/shared/SearchInput.esm.js.map +1 -0
  41. package/dist/constants/index.esm.js +38 -0
  42. package/dist/constants/index.esm.js.map +1 -0
  43. package/dist/hooks/useFlagsmithProject.esm.js +49 -0
  44. package/dist/hooks/useFlagsmithProject.esm.js.map +1 -0
  45. package/dist/hooks/useFlagsmithUsage.esm.js +44 -0
  46. package/dist/hooks/useFlagsmithUsage.esm.js.map +1 -0
  47. package/dist/index.d.ts +111 -0
  48. package/dist/index.esm.js +41 -0
  49. package/dist/index.esm.js.map +1 -0
  50. package/dist/theme/flagsmithTheme.esm.js +28 -0
  51. package/dist/theme/flagsmithTheme.esm.js.map +1 -0
  52. package/dist/theme/sharedStyles.esm.js +19 -0
  53. package/dist/theme/sharedStyles.esm.js.map +1 -0
  54. package/dist/utils/dateFormatters.esm.js +15 -0
  55. package/dist/utils/dateFormatters.esm.js.map +1 -0
  56. package/dist/utils/flagHelpers.esm.js +25 -0
  57. package/dist/utils/flagHelpers.esm.js.map +1 -0
  58. package/dist/utils/flagTypeHelpers.esm.js +42 -0
  59. package/dist/utils/flagTypeHelpers.esm.js.map +1 -0
  60. package/package.json +108 -0
@@ -0,0 +1,84 @@
1
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import { Box, Typography } from '@material-ui/core';
3
+ import { ResponsiveContainer, BarChart, CartesianGrid, XAxis, YAxis, Tooltip, Bar } from 'recharts';
4
+ import { flagsmithColors } from '../../theme/flagsmithTheme.esm.js';
5
+ import '../shared/FlagStatusIndicator.esm.js';
6
+ import '../shared/SearchInput.esm.js';
7
+ import '../shared/FlagsmithLink.esm.js';
8
+ import '@material-ui/icons/ChevronLeft';
9
+ import '@material-ui/icons/ChevronRight';
10
+ import { ChartTooltip, ChartTooltipText } from '../shared/ChartTooltip.esm.js';
11
+
12
+ const UsageChartTooltip = ({ active, payload }) => /* @__PURE__ */ jsx(ChartTooltip, { active, payload, children: (data) => {
13
+ const usageData = data[0].payload;
14
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
15
+ /* @__PURE__ */ jsx(ChartTooltipText, { variant: "subtitle2", fontWeight: 600, children: new Date(usageData.day).toLocaleDateString("en-US", {
16
+ month: "short",
17
+ day: "numeric",
18
+ year: "numeric"
19
+ }) }),
20
+ /* @__PURE__ */ jsxs(Box, { mt: 1, children: [
21
+ /* @__PURE__ */ jsxs(ChartTooltipText, { children: [
22
+ /* @__PURE__ */ jsx("strong", { children: "Flags:" }),
23
+ " ",
24
+ usageData.flags ?? 0
25
+ ] }),
26
+ /* @__PURE__ */ jsxs(ChartTooltipText, { children: [
27
+ /* @__PURE__ */ jsx("strong", { children: "Identities:" }),
28
+ " ",
29
+ usageData.identities
30
+ ] }),
31
+ /* @__PURE__ */ jsxs(ChartTooltipText, { children: [
32
+ /* @__PURE__ */ jsx("strong", { children: "Traits:" }),
33
+ " ",
34
+ usageData.traits
35
+ ] }),
36
+ /* @__PURE__ */ jsxs(ChartTooltipText, { children: [
37
+ /* @__PURE__ */ jsx("strong", { children: "Environment Document:" }),
38
+ " ",
39
+ usageData.environment_document
40
+ ] })
41
+ ] })
42
+ ] });
43
+ } });
44
+ const UsageChart = ({ data }) => {
45
+ if (data.length === 0) {
46
+ return /* @__PURE__ */ jsx(Box, { display: "flex", justifyContent: "center", alignItems: "center", height: 300, children: /* @__PURE__ */ jsx(Typography, { color: "textSecondary", children: "No usage data available" }) });
47
+ }
48
+ return /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: 300, children: /* @__PURE__ */ jsxs(
49
+ BarChart,
50
+ {
51
+ data,
52
+ margin: { top: 5, right: 30, left: 20, bottom: 5 },
53
+ children: [
54
+ /* @__PURE__ */ jsx(CartesianGrid, { strokeDasharray: "3 3" }),
55
+ /* @__PURE__ */ jsx(
56
+ XAxis,
57
+ {
58
+ dataKey: "day",
59
+ tickFormatter: (value) => {
60
+ const date = new Date(value);
61
+ return `${date.getMonth() + 1}/${date.getDate()}`;
62
+ },
63
+ angle: -45,
64
+ textAnchor: "end",
65
+ height: 80
66
+ }
67
+ ),
68
+ /* @__PURE__ */ jsx(YAxis, {}),
69
+ /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(UsageChartTooltip, {}) }),
70
+ /* @__PURE__ */ jsx(
71
+ Bar,
72
+ {
73
+ dataKey: "flags",
74
+ fill: flagsmithColors.primary,
75
+ radius: [2, 2, 0, 0]
76
+ }
77
+ )
78
+ ]
79
+ }
80
+ ) });
81
+ };
82
+
83
+ export { UsageChart };
84
+ //# sourceMappingURL=UsageChart.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UsageChart.esm.js","sources":["../../../src/components/FlagsmithUsageCard/UsageChart.tsx"],"sourcesContent":["import { Box, Typography } from '@material-ui/core';\nimport {\n BarChart,\n Bar,\n XAxis,\n YAxis,\n CartesianGrid,\n Tooltip,\n ResponsiveContainer,\n} from 'recharts';\nimport { FlagsmithUsageData } from '../../api/FlagsmithClient';\nimport { flagsmithColors } from '../../theme/flagsmithTheme';\nimport { ChartTooltip, ChartTooltipText } from '../shared';\n\ninterface UsageChartProps {\n data: FlagsmithUsageData[];\n}\n\n/**\n * Custom tooltip for usage chart displaying flags, identities, traits, and environment document\n */\nconst UsageChartTooltip = ({ active, payload }: any) => (\n <ChartTooltip active={active} payload={payload}>\n {(data) => {\n const usageData = data[0].payload as FlagsmithUsageData;\n return (\n <>\n <ChartTooltipText variant=\"subtitle2\" fontWeight={600}>\n {new Date(usageData.day).toLocaleDateString('en-US', {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n })}\n </ChartTooltipText>\n <Box mt={1}>\n <ChartTooltipText>\n <strong>Flags:</strong> {usageData.flags ?? 0}\n </ChartTooltipText>\n <ChartTooltipText>\n <strong>Identities:</strong> {usageData.identities}\n </ChartTooltipText>\n <ChartTooltipText>\n <strong>Traits:</strong> {usageData.traits}\n </ChartTooltipText>\n <ChartTooltipText>\n <strong>Environment Document:</strong> {usageData.environment_document}\n </ChartTooltipText>\n </Box>\n </>\n );\n }}\n </ChartTooltip>\n);\n\nexport const UsageChart = ({ data }: UsageChartProps) => {\n if (data.length === 0) {\n return (\n <Box display=\"flex\" justifyContent=\"center\" alignItems=\"center\" height={300}>\n <Typography color=\"textSecondary\">\n No usage data available\n </Typography>\n </Box>\n );\n }\n\n return (\n <ResponsiveContainer width=\"100%\" height={300}>\n <BarChart\n data={data}\n margin={{ top: 5, right: 30, left: 20, bottom: 5 }}\n >\n <CartesianGrid strokeDasharray=\"3 3\" />\n <XAxis\n dataKey=\"day\"\n tickFormatter={value => {\n const date = new Date(value);\n return `${date.getMonth() + 1}/${date.getDate()}`;\n }}\n angle={-45}\n textAnchor=\"end\"\n height={80}\n />\n <YAxis />\n <Tooltip content={<UsageChartTooltip />} />\n <Bar\n dataKey=\"flags\"\n fill={flagsmithColors.primary}\n radius={[2, 2, 0, 0]}\n />\n </BarChart>\n </ResponsiveContainer>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { Box } from '@material-ui/core';
3
+ import { makeStyles } from '@material-ui/core/styles';
4
+ import { InfoCard } from '@backstage/core-components';
5
+ import { useEntity } from '@backstage/plugin-catalog-react';
6
+ import '../shared/FlagStatusIndicator.esm.js';
7
+ import '../shared/SearchInput.esm.js';
8
+ import { FlagsmithLink } from '../shared/FlagsmithLink.esm.js';
9
+ import '@material-ui/icons/ChevronLeft';
10
+ import '@material-ui/icons/ChevronRight';
11
+ import { LoadingState } from '../shared/LoadingState.esm.js';
12
+ import { ErrorState } from '../shared/ErrorState.esm.js';
13
+ import '../shared/ChartTooltip.esm.js';
14
+ import { FLAGSMITH_DASHBOARD_URL } from '../../theme/flagsmithTheme.esm.js';
15
+ import 'react';
16
+ import '@backstage/core-plugin-api';
17
+ import { useFlagsmithUsage } from '../../hooks/useFlagsmithUsage.esm.js';
18
+ import { UsageChart } from './UsageChart.esm.js';
19
+
20
+ const useStyles = makeStyles((theme) => ({
21
+ headerActions: {
22
+ display: "flex",
23
+ alignItems: "center",
24
+ gap: theme.spacing(1)
25
+ }
26
+ }));
27
+ const FlagsmithUsageCard = () => {
28
+ const classes = useStyles();
29
+ const { entity } = useEntity();
30
+ const projectId = entity.metadata.annotations?.["flagsmith.com/project-id"];
31
+ const orgId = entity.metadata.annotations?.["flagsmith.com/org-id"];
32
+ const { project, usageData, totalFlags, loading, error } = useFlagsmithUsage(
33
+ projectId,
34
+ orgId
35
+ );
36
+ const usageUrl = `${FLAGSMITH_DASHBOARD_URL}/organisation/${orgId}/usage`;
37
+ if (loading) {
38
+ return /* @__PURE__ */ jsx(InfoCard, { title: "Flags Usage Data (30 Days)", children: /* @__PURE__ */ jsx(LoadingState, { message: "Loading usage data...", size: 24 }) });
39
+ }
40
+ if (error) {
41
+ return /* @__PURE__ */ jsx(InfoCard, { title: "Flags Usage Data (30 Days)", children: /* @__PURE__ */ jsx(
42
+ ErrorState,
43
+ {
44
+ message: error,
45
+ hint: !orgId ? "Add a flagsmith.com/organization-id annotation to this entity." : void 0
46
+ }
47
+ ) });
48
+ }
49
+ const subheader = project?.name ? `${project.name} - ${totalFlags.toLocaleString()} total flag calls` : void 0;
50
+ return /* @__PURE__ */ jsx(
51
+ InfoCard,
52
+ {
53
+ title: "Flags Usage Data (30 Days)",
54
+ subheader,
55
+ action: orgId && /* @__PURE__ */ jsx(Box, { className: classes.headerActions, children: /* @__PURE__ */ jsx(FlagsmithLink, { href: usageUrl, iconOnly: true, tooltip: "View Usage Analytics" }) }),
56
+ children: /* @__PURE__ */ jsx(Box, { p: 2, children: /* @__PURE__ */ jsx(UsageChart, { data: usageData }) })
57
+ }
58
+ );
59
+ };
60
+
61
+ export { FlagsmithUsageCard };
62
+ //# sourceMappingURL=index.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.esm.js","sources":["../../../src/components/FlagsmithUsageCard/index.tsx"],"sourcesContent":["import { Box } from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { InfoCard } from '@backstage/core-components';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport { FlagsmithLink, LoadingState, ErrorState } from '../shared';\nimport { FLAGSMITH_DASHBOARD_URL } from '../../theme/flagsmithTheme';\nimport { useFlagsmithUsage } from '../../hooks';\nimport { UsageChart } from './UsageChart';\n\nconst useStyles = makeStyles(theme => ({\n headerActions: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(1),\n },\n}));\n\nexport const FlagsmithUsageCard = () => {\n const classes = useStyles();\n const { entity } = useEntity();\n\n const projectId = entity.metadata.annotations?.['flagsmith.com/project-id'];\n const orgId = entity.metadata.annotations?.['flagsmith.com/org-id'];\n\n const { project, usageData, totalFlags, loading, error } = useFlagsmithUsage(\n projectId,\n orgId,\n );\n\n const usageUrl = `${FLAGSMITH_DASHBOARD_URL}/organisation/${orgId}/usage`;\n\n if (loading) {\n return (\n <InfoCard title=\"Flags Usage Data (30 Days)\">\n <LoadingState message=\"Loading usage data...\" size={24} />\n </InfoCard>\n );\n }\n\n if (error) {\n return (\n <InfoCard title=\"Flags Usage Data (30 Days)\">\n <ErrorState\n message={error}\n hint={!orgId ? 'Add a flagsmith.com/organization-id annotation to this entity.' : undefined}\n />\n </InfoCard>\n );\n }\n\n const subheader = project?.name\n ? `${project.name} - ${totalFlags.toLocaleString()} total flag calls`\n : undefined;\n\n return (\n <InfoCard\n title=\"Flags Usage Data (30 Days)\"\n subheader={subheader}\n action={\n orgId && (\n <Box className={classes.headerActions}>\n <FlagsmithLink href={usageUrl} iconOnly tooltip=\"View Usage Analytics\" />\n </Box>\n )\n }\n >\n <Box p={2}>\n <UsageChart data={usageData} />\n </Box>\n </InfoCard>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;AASA,MAAM,SAAA,GAAY,WAAW,CAAA,KAAA,MAAU;AAAA,EACrC,aAAA,EAAe;AAAA,IACb,OAAA,EAAS,MAAA;AAAA,IACT,UAAA,EAAY,QAAA;AAAA,IACZ,GAAA,EAAK,KAAA,CAAM,OAAA,CAAQ,CAAC;AAAA;AAExB,CAAA,CAAE,CAAA;AAEK,MAAM,qBAAqB,MAAM;AACtC,EAAA,MAAM,UAAU,SAAA,EAAU;AAC1B,EAAA,MAAM,EAAE,MAAA,EAAO,GAAI,SAAA,EAAU;AAE7B,EAAA,MAAM,SAAA,GAAY,MAAA,CAAO,QAAA,CAAS,WAAA,GAAc,0BAA0B,CAAA;AAC1E,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,QAAA,CAAS,WAAA,GAAc,sBAAsB,CAAA;AAElE,EAAA,MAAM,EAAE,OAAA,EAAS,SAAA,EAAW,UAAA,EAAY,OAAA,EAAS,OAAM,GAAI,iBAAA;AAAA,IACzD,SAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,MAAM,QAAA,GAAW,CAAA,EAAG,uBAAuB,CAAA,cAAA,EAAiB,KAAK,CAAA,MAAA,CAAA;AAEjE,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,uBACE,GAAA,CAAC,QAAA,EAAA,EAAS,KAAA,EAAM,4BAAA,EACd,QAAA,kBAAA,GAAA,CAAC,gBAAa,OAAA,EAAQ,uBAAA,EAAwB,IAAA,EAAM,EAAA,EAAI,CAAA,EAC1D,CAAA;AAAA,EAEJ;AAEA,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,uBACE,GAAA,CAAC,QAAA,EAAA,EAAS,KAAA,EAAM,4BAAA,EACd,QAAA,kBAAA,GAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACC,OAAA,EAAS,KAAA;AAAA,QACT,IAAA,EAAM,CAAC,KAAA,GAAQ,gEAAA,GAAmE;AAAA;AAAA,KACpF,EACF,CAAA;AAAA,EAEJ;AAEA,EAAA,MAAM,SAAA,GAAY,OAAA,EAAS,IAAA,GACvB,CAAA,EAAG,OAAA,CAAQ,IAAI,CAAA,GAAA,EAAM,UAAA,CAAW,cAAA,EAAgB,CAAA,iBAAA,CAAA,GAChD,MAAA;AAEJ,EAAA,uBACE,GAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAM,4BAAA;AAAA,MACN,SAAA;AAAA,MACA,MAAA,EACE,KAAA,oBACE,GAAA,CAAC,GAAA,EAAA,EAAI,WAAW,OAAA,CAAQ,aAAA,EACtB,QAAA,kBAAA,GAAA,CAAC,aAAA,EAAA,EAAc,MAAM,QAAA,EAAU,QAAA,EAAQ,IAAA,EAAC,OAAA,EAAQ,wBAAuB,CAAA,EACzE,CAAA;AAAA,MAIJ,QAAA,kBAAA,GAAA,CAAC,OAAI,CAAA,EAAG,CAAA,EACN,8BAAC,UAAA,EAAA,EAAW,IAAA,EAAM,WAAW,CAAA,EAC/B;AAAA;AAAA,GACF;AAEJ;;;;"}
@@ -0,0 +1,33 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { Box, Typography } from '@material-ui/core';
3
+ import { makeStyles } from '@material-ui/core/styles';
4
+
5
+ const useStyles = makeStyles((theme) => ({
6
+ tooltipBox: {
7
+ backgroundColor: theme.palette.grey[800],
8
+ border: "none",
9
+ borderRadius: theme.shape.borderRadius,
10
+ boxShadow: "0 2px 8px rgba(0,0,0,0.15)"
11
+ },
12
+ tooltipText: {
13
+ color: theme.palette.common.white
14
+ }
15
+ }));
16
+ const ChartTooltip = ({ active, payload, label, children }) => {
17
+ const classes = useStyles();
18
+ if (!active || !payload?.length) {
19
+ return null;
20
+ }
21
+ return /* @__PURE__ */ jsx(Box, { p: 1.5, className: classes.tooltipBox, children: children(payload, label) });
22
+ };
23
+ const ChartTooltipText = ({
24
+ variant = "body2",
25
+ fontWeight,
26
+ children
27
+ }) => {
28
+ const classes = useStyles();
29
+ return /* @__PURE__ */ jsx(Typography, { variant, className: classes.tooltipText, style: { fontWeight }, children });
30
+ };
31
+
32
+ export { ChartTooltip, ChartTooltipText };
33
+ //# sourceMappingURL=ChartTooltip.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChartTooltip.esm.js","sources":["../../../src/components/shared/ChartTooltip.tsx"],"sourcesContent":["import { Box, Typography } from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { ReactNode } from 'react';\n\nconst useStyles = makeStyles((theme) => ({\n tooltipBox: {\n backgroundColor: theme.palette.grey[800],\n border: 'none',\n borderRadius: theme.shape.borderRadius,\n boxShadow: '0 2px 8px rgba(0,0,0,0.15)',\n },\n tooltipText: {\n color: theme.palette.common.white,\n },\n}));\n\ninterface ChartTooltipProps {\n active?: boolean;\n payload?: any[];\n label?: string;\n children: (payload: any[], label?: string) => ReactNode;\n}\n\n/**\n * Generic Recharts custom tooltip component\n * Uses theme colors for consistent theming across light and dark modes\n * Accepts a render function to customize content per use case\n *\n * @example\n * <Tooltip content={\n * <ChartTooltip>\n * {(payload, label) => (\n * <>\n * <ChartTooltipText variant=\"subtitle2\">{label}</ChartTooltipText>\n * <ChartTooltipText>Value: {payload[0].value}</ChartTooltipText>\n * </>\n * )}\n * </ChartTooltip>\n * } />\n */\nexport const ChartTooltip = ({ active, payload, label, children }: ChartTooltipProps) => {\n const classes = useStyles();\n\n if (!active || !payload?.length) {\n return null;\n }\n\n return (\n <Box p={1.5} className={classes.tooltipBox}>\n {children(payload, label)}\n </Box>\n );\n};\n\ninterface ChartTooltipTextProps {\n variant?: 'subtitle2' | 'body2';\n fontWeight?: number;\n children: ReactNode;\n}\n\n/**\n * Text component for chart tooltips with theme-aware white color\n */\nexport const ChartTooltipText = ({\n variant = 'body2',\n fontWeight,\n children,\n}: ChartTooltipTextProps) => {\n const classes = useStyles();\n\n return (\n <Typography variant={variant} className={classes.tooltipText} style={{ fontWeight }}>\n {children}\n </Typography>\n );\n};\n"],"names":[],"mappings":";;;;AAIA,MAAM,SAAA,GAAY,UAAA,CAAW,CAAC,KAAA,MAAW;AAAA,EACvC,UAAA,EAAY;AAAA,IACV,eAAA,EAAiB,KAAA,CAAM,OAAA,CAAQ,IAAA,CAAK,GAAG,CAAA;AAAA,IACvC,MAAA,EAAQ,MAAA;AAAA,IACR,YAAA,EAAc,MAAM,KAAA,CAAM,YAAA;AAAA,IAC1B,SAAA,EAAW;AAAA,GACb;AAAA,EACA,WAAA,EAAa;AAAA,IACX,KAAA,EAAO,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO;AAAA;AAEhC,CAAA,CAAE,CAAA;AA0BK,MAAM,eAAe,CAAC,EAAE,QAAQ,OAAA,EAAS,KAAA,EAAO,UAAS,KAAyB;AACvF,EAAA,MAAM,UAAU,SAAA,EAAU;AAE1B,EAAA,IAAI,CAAC,MAAA,IAAU,CAAC,OAAA,EAAS,MAAA,EAAQ;AAC/B,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,uBACE,GAAA,CAAC,GAAA,EAAA,EAAI,CAAA,EAAG,GAAA,EAAK,SAAA,EAAW,QAAQ,UAAA,EAC7B,QAAA,EAAA,QAAA,CAAS,OAAA,EAAS,KAAK,CAAA,EAC1B,CAAA;AAEJ;AAWO,MAAM,mBAAmB,CAAC;AAAA,EAC/B,OAAA,GAAU,OAAA;AAAA,EACV,UAAA;AAAA,EACA;AACF,CAAA,KAA6B;AAC3B,EAAA,MAAM,UAAU,SAAA,EAAU;AAE1B,EAAA,uBACE,GAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAkB,SAAA,EAAW,OAAA,CAAQ,aAAa,KAAA,EAAO,EAAE,UAAA,EAAW,EAC/E,QAAA,EACH,CAAA;AAEJ;;;;"}
@@ -0,0 +1,13 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { Box, Typography } from '@material-ui/core';
3
+
4
+ const ErrorState = ({ message, hint }) => /* @__PURE__ */ jsxs(Box, { p: 2, children: [
5
+ /* @__PURE__ */ jsxs(Typography, { color: "error", children: [
6
+ "Error: ",
7
+ message
8
+ ] }),
9
+ hint && /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "textSecondary", style: { marginTop: 8 }, children: hint })
10
+ ] });
11
+
12
+ export { ErrorState };
13
+ //# sourceMappingURL=ErrorState.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ErrorState.esm.js","sources":["../../../src/components/shared/ErrorState.tsx"],"sourcesContent":["import { Box, Typography } from '@material-ui/core';\n\ninterface ErrorStateProps {\n message: string;\n hint?: string;\n}\n\nexport const ErrorState = ({ message, hint }: ErrorStateProps) => (\n <Box p={2}>\n <Typography color=\"error\">Error: {message}</Typography>\n {hint && (\n <Typography variant=\"body2\" color=\"textSecondary\" style={{ marginTop: 8 }}>\n {hint}\n </Typography>\n )}\n </Box>\n);\n"],"names":[],"mappings":";;;AAOO,MAAM,UAAA,GAAa,CAAC,EAAE,OAAA,EAAS,MAAK,qBACzC,IAAA,CAAC,GAAA,EAAA,EAAI,CAAA,EAAG,CAAA,EACN,QAAA,EAAA;AAAA,kBAAA,IAAA,CAAC,UAAA,EAAA,EAAW,OAAM,OAAA,EAAQ,QAAA,EAAA;AAAA,IAAA,SAAA;AAAA,IAAQ;AAAA,GAAA,EAAQ,CAAA;AAAA,EACzC,IAAA,oBACC,GAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,OAAA,EAAQ,KAAA,EAAM,eAAA,EAAgB,KAAA,EAAO,EAAE,SAAA,EAAW,CAAA,EAAE,EACrE,QAAA,EAAA,IAAA,EACH;AAAA,CAAA,EAEJ;;;;"}
@@ -0,0 +1,61 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { Box, Typography, Tooltip } from '@material-ui/core';
3
+ import { makeStyles } from '@material-ui/core/styles';
4
+ import { flagsmithColors } from '../../theme/flagsmithTheme.esm.js';
5
+
6
+ const useStyles = makeStyles(() => ({
7
+ container: {
8
+ display: "flex",
9
+ alignItems: "center",
10
+ gap: 6
11
+ },
12
+ dot: {
13
+ width: 10,
14
+ height: 10,
15
+ borderRadius: "50%",
16
+ flexShrink: 0
17
+ },
18
+ enabled: {
19
+ backgroundColor: flagsmithColors.enabled
20
+ },
21
+ disabled: {
22
+ backgroundColor: flagsmithColors.disabled
23
+ },
24
+ label: {
25
+ fontSize: "0.875rem"
26
+ }
27
+ }));
28
+ const FlagStatusIndicator = ({
29
+ enabled,
30
+ showLabel = false,
31
+ size = "medium",
32
+ tooltip
33
+ }) => {
34
+ const classes = useStyles();
35
+ const dotSize = size === "small" ? 8 : 10;
36
+ const indicator = /* @__PURE__ */ jsxs(Box, { className: classes.container, children: [
37
+ /* @__PURE__ */ jsx(
38
+ Box,
39
+ {
40
+ className: `${classes.dot} ${enabled ? classes.enabled : classes.disabled}`,
41
+ style: { width: dotSize, height: dotSize }
42
+ }
43
+ ),
44
+ showLabel && /* @__PURE__ */ jsx(
45
+ Typography,
46
+ {
47
+ variant: "body2",
48
+ className: classes.label,
49
+ style: { fontSize: size === "small" ? "0.75rem" : "0.875rem" },
50
+ children: enabled ? "On" : "Off"
51
+ }
52
+ )
53
+ ] });
54
+ if (tooltip) {
55
+ return /* @__PURE__ */ jsx(Tooltip, { title: tooltip, children: indicator });
56
+ }
57
+ return indicator;
58
+ };
59
+
60
+ export { FlagStatusIndicator };
61
+ //# sourceMappingURL=FlagStatusIndicator.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FlagStatusIndicator.esm.js","sources":["../../../src/components/shared/FlagStatusIndicator.tsx"],"sourcesContent":["import { Box, Typography, Tooltip } from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { flagsmithColors } from '../../theme/flagsmithTheme';\n\nconst useStyles = makeStyles(() => ({\n container: {\n display: 'flex',\n alignItems: 'center',\n gap: 6,\n },\n dot: {\n width: 10,\n height: 10,\n borderRadius: '50%',\n flexShrink: 0,\n },\n enabled: {\n backgroundColor: flagsmithColors.enabled,\n },\n disabled: {\n backgroundColor: flagsmithColors.disabled,\n },\n label: {\n fontSize: '0.875rem',\n },\n}));\n\ninterface FlagStatusIndicatorProps {\n enabled: boolean;\n showLabel?: boolean;\n size?: 'small' | 'medium';\n tooltip?: string;\n}\n\n/**\n * Visual indicator for flag enabled/disabled status\n * Shows a colored dot (green for enabled, gray for disabled)\n */\nexport const FlagStatusIndicator = ({\n enabled,\n showLabel = false,\n size = 'medium',\n tooltip,\n}: FlagStatusIndicatorProps) => {\n const classes = useStyles();\n\n const dotSize = size === 'small' ? 8 : 10;\n\n const indicator = (\n <Box className={classes.container}>\n <Box\n className={`${classes.dot} ${enabled ? classes.enabled : classes.disabled}`}\n style={{ width: dotSize, height: dotSize }}\n />\n {showLabel && (\n <Typography\n variant=\"body2\"\n className={classes.label}\n style={{ fontSize: size === 'small' ? '0.75rem' : '0.875rem' }}\n >\n {enabled ? 'On' : 'Off'}\n </Typography>\n )}\n </Box>\n );\n\n if (tooltip) {\n return <Tooltip title={tooltip}>{indicator}</Tooltip>;\n }\n\n return indicator;\n};\n"],"names":[],"mappings":";;;;;AAIA,MAAM,SAAA,GAAY,WAAW,OAAO;AAAA,EAClC,SAAA,EAAW;AAAA,IACT,OAAA,EAAS,MAAA;AAAA,IACT,UAAA,EAAY,QAAA;AAAA,IACZ,GAAA,EAAK;AAAA,GACP;AAAA,EACA,GAAA,EAAK;AAAA,IACH,KAAA,EAAO,EAAA;AAAA,IACP,MAAA,EAAQ,EAAA;AAAA,IACR,YAAA,EAAc,KAAA;AAAA,IACd,UAAA,EAAY;AAAA,GACd;AAAA,EACA,OAAA,EAAS;AAAA,IACP,iBAAiB,eAAA,CAAgB;AAAA,GACnC;AAAA,EACA,QAAA,EAAU;AAAA,IACR,iBAAiB,eAAA,CAAgB;AAAA,GACnC;AAAA,EACA,KAAA,EAAO;AAAA,IACL,QAAA,EAAU;AAAA;AAEd,CAAA,CAAE,CAAA;AAaK,MAAM,sBAAsB,CAAC;AAAA,EAClC,OAAA;AAAA,EACA,SAAA,GAAY,KAAA;AAAA,EACZ,IAAA,GAAO,QAAA;AAAA,EACP;AACF,CAAA,KAAgC;AAC9B,EAAA,MAAM,UAAU,SAAA,EAAU;AAE1B,EAAA,MAAM,OAAA,GAAU,IAAA,KAAS,OAAA,GAAU,CAAA,GAAI,EAAA;AAEvC,EAAA,MAAM,SAAA,mBACJ,IAAA,CAAC,GAAA,EAAA,EAAI,SAAA,EAAW,QAAQ,SAAA,EACtB,QAAA,EAAA;AAAA,oBAAA,GAAA;AAAA,MAAC,GAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAW,GAAG,OAAA,CAAQ,GAAG,IAAI,OAAA,GAAU,OAAA,CAAQ,OAAA,GAAU,OAAA,CAAQ,QAAQ,CAAA,CAAA;AAAA,QACzE,KAAA,EAAO,EAAE,KAAA,EAAO,OAAA,EAAS,QAAQ,OAAA;AAAQ;AAAA,KAC3C;AAAA,IACC,SAAA,oBACC,GAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACC,OAAA,EAAQ,OAAA;AAAA,QACR,WAAW,OAAA,CAAQ,KAAA;AAAA,QACnB,OAAO,EAAE,QAAA,EAAU,IAAA,KAAS,OAAA,GAAU,YAAY,UAAA,EAAW;AAAA,QAE5D,oBAAU,IAAA,GAAO;AAAA;AAAA;AACpB,GAAA,EAEJ,CAAA;AAGF,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,uBAAO,GAAA,CAAC,OAAA,EAAA,EAAQ,KAAA,EAAO,OAAA,EAAU,QAAA,EAAA,SAAA,EAAU,CAAA;AAAA,EAC7C;AAEA,EAAA,OAAO,SAAA;AACT;;;;"}
@@ -0,0 +1,74 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { Tooltip, IconButton, Link } from '@material-ui/core';
3
+ import { makeStyles } from '@material-ui/core/styles';
4
+ import LaunchIcon from '@material-ui/icons/Launch';
5
+ import { flagsmithColors } from '../../theme/flagsmithTheme.esm.js';
6
+
7
+ const useStyles = makeStyles((theme) => ({
8
+ link: {
9
+ display: "inline-flex",
10
+ alignItems: "center",
11
+ gap: 4,
12
+ color: "inherit",
13
+ textDecoration: "none",
14
+ "&:hover": {
15
+ color: flagsmithColors.primary,
16
+ textDecoration: "underline"
17
+ }
18
+ },
19
+ icon: {
20
+ fontSize: "0.875rem",
21
+ opacity: 0.7
22
+ },
23
+ iconButton: {
24
+ padding: 4,
25
+ color: flagsmithColors.primary
26
+ },
27
+ tooltip: {
28
+ backgroundColor: theme.palette.grey[700],
29
+ color: theme.palette.common.white,
30
+ fontSize: "0.75rem"
31
+ }
32
+ }));
33
+ const FlagsmithLink = ({
34
+ href,
35
+ children,
36
+ tooltip = "Open in Flagsmith",
37
+ iconOnly = false,
38
+ onClick
39
+ }) => {
40
+ const classes = useStyles();
41
+ if (iconOnly) {
42
+ return /* @__PURE__ */ jsx(Tooltip, { title: tooltip, classes: { tooltip: classes.tooltip }, children: /* @__PURE__ */ jsx(
43
+ IconButton,
44
+ {
45
+ className: classes.iconButton,
46
+ href,
47
+ target: "_blank",
48
+ rel: "noopener noreferrer",
49
+ size: "small",
50
+ "aria-label": tooltip,
51
+ onClick,
52
+ children: /* @__PURE__ */ jsx(LaunchIcon, { fontSize: "small", "aria-hidden": "true" })
53
+ }
54
+ ) });
55
+ }
56
+ return /* @__PURE__ */ jsx(Tooltip, { title: tooltip, classes: { tooltip: classes.tooltip }, children: /* @__PURE__ */ jsxs(
57
+ Link,
58
+ {
59
+ className: classes.link,
60
+ href,
61
+ target: "_blank",
62
+ rel: "noopener noreferrer",
63
+ "aria-label": `${tooltip} (opens in new tab)`,
64
+ onClick,
65
+ children: [
66
+ children,
67
+ /* @__PURE__ */ jsx(LaunchIcon, { className: classes.icon, "aria-hidden": "true" })
68
+ ]
69
+ }
70
+ ) });
71
+ };
72
+
73
+ export { FlagsmithLink };
74
+ //# sourceMappingURL=FlagsmithLink.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FlagsmithLink.esm.js","sources":["../../../src/components/shared/FlagsmithLink.tsx"],"sourcesContent":["import { Link, Tooltip, IconButton } from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport LaunchIcon from '@material-ui/icons/Launch';\nimport { flagsmithColors } from '../../theme/flagsmithTheme';\n\nconst useStyles = makeStyles(theme => ({\n link: {\n display: 'inline-flex',\n alignItems: 'center',\n gap: 4,\n color: 'inherit',\n textDecoration: 'none',\n '&:hover': {\n color: flagsmithColors.primary,\n textDecoration: 'underline',\n },\n },\n icon: {\n fontSize: '0.875rem',\n opacity: 0.7,\n },\n iconButton: {\n padding: 4,\n color: flagsmithColors.primary,\n },\n tooltip: {\n backgroundColor: theme.palette.grey[700],\n color: theme.palette.common.white,\n fontSize: '0.75rem',\n },\n}));\n\ninterface FlagsmithLinkProps {\n href: string;\n children?: React.ReactNode;\n tooltip?: string;\n iconOnly?: boolean;\n onClick?: (event: React.MouseEvent) => void;\n}\n\n/**\n * External link to Flagsmith dashboard\n * Opens in a new tab with appropriate security attributes\n */\nexport const FlagsmithLink = ({\n href,\n children,\n tooltip = 'Open in Flagsmith',\n iconOnly = false,\n onClick,\n}: FlagsmithLinkProps) => {\n const classes = useStyles();\n\n if (iconOnly) {\n return (\n <Tooltip title={tooltip} classes={{ tooltip: classes.tooltip }}>\n <IconButton\n className={classes.iconButton}\n href={href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n size=\"small\"\n aria-label={tooltip}\n onClick={onClick}\n >\n <LaunchIcon fontSize=\"small\" aria-hidden=\"true\" />\n </IconButton>\n </Tooltip>\n );\n }\n\n return (\n <Tooltip title={tooltip} classes={{ tooltip: classes.tooltip }}>\n <Link\n className={classes.link}\n href={href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label={`${tooltip} (opens in new tab)`}\n onClick={onClick}\n >\n {children}\n <LaunchIcon className={classes.icon} aria-hidden=\"true\" />\n </Link>\n </Tooltip>\n );\n};\n"],"names":[],"mappings":";;;;;;AAKA,MAAM,SAAA,GAAY,WAAW,CAAA,KAAA,MAAU;AAAA,EACrC,IAAA,EAAM;AAAA,IACJ,OAAA,EAAS,aAAA;AAAA,IACT,UAAA,EAAY,QAAA;AAAA,IACZ,GAAA,EAAK,CAAA;AAAA,IACL,KAAA,EAAO,SAAA;AAAA,IACP,cAAA,EAAgB,MAAA;AAAA,IAChB,SAAA,EAAW;AAAA,MACT,OAAO,eAAA,CAAgB,OAAA;AAAA,MACvB,cAAA,EAAgB;AAAA;AAClB,GACF;AAAA,EACA,IAAA,EAAM;AAAA,IACJ,QAAA,EAAU,UAAA;AAAA,IACV,OAAA,EAAS;AAAA,GACX;AAAA,EACA,UAAA,EAAY;AAAA,IACV,OAAA,EAAS,CAAA;AAAA,IACT,OAAO,eAAA,CAAgB;AAAA,GACzB;AAAA,EACA,OAAA,EAAS;AAAA,IACP,eAAA,EAAiB,KAAA,CAAM,OAAA,CAAQ,IAAA,CAAK,GAAG,CAAA;AAAA,IACvC,KAAA,EAAO,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO,KAAA;AAAA,IAC5B,QAAA,EAAU;AAAA;AAEd,CAAA,CAAE,CAAA;AAcK,MAAM,gBAAgB,CAAC;AAAA,EAC5B,IAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA,GAAU,mBAAA;AAAA,EACV,QAAA,GAAW,KAAA;AAAA,EACX;AACF,CAAA,KAA0B;AACxB,EAAA,MAAM,UAAU,SAAA,EAAU;AAE1B,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,uBACE,GAAA,CAAC,WAAQ,KAAA,EAAO,OAAA,EAAS,SAAS,EAAE,OAAA,EAAS,OAAA,CAAQ,OAAA,EAAQ,EAC3D,QAAA,kBAAA,GAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACC,WAAW,OAAA,CAAQ,UAAA;AAAA,QACnB,IAAA;AAAA,QACA,MAAA,EAAO,QAAA;AAAA,QACP,GAAA,EAAI,qBAAA;AAAA,QACJ,IAAA,EAAK,OAAA;AAAA,QACL,YAAA,EAAY,OAAA;AAAA,QACZ,OAAA;AAAA,QAEA,QAAA,kBAAA,GAAA,CAAC,UAAA,EAAA,EAAW,QAAA,EAAS,OAAA,EAAQ,eAAY,MAAA,EAAO;AAAA;AAAA,KAClD,EACF,CAAA;AAAA,EAEJ;AAEA,EAAA,uBACE,GAAA,CAAC,WAAQ,KAAA,EAAO,OAAA,EAAS,SAAS,EAAE,OAAA,EAAS,OAAA,CAAQ,OAAA,EAAQ,EAC3D,QAAA,kBAAA,IAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MACC,WAAW,OAAA,CAAQ,IAAA;AAAA,MACnB,IAAA;AAAA,MACA,MAAA,EAAO,QAAA;AAAA,MACP,GAAA,EAAI,qBAAA;AAAA,MACJ,YAAA,EAAY,GAAG,OAAO,CAAA,mBAAA,CAAA;AAAA,MACtB,OAAA;AAAA,MAEC,QAAA,EAAA;AAAA,QAAA,QAAA;AAAA,4BACA,UAAA,EAAA,EAAW,SAAA,EAAW,OAAA,CAAQ,IAAA,EAAM,eAAY,MAAA,EAAO;AAAA;AAAA;AAAA,GAC1D,EACF,CAAA;AAEJ;;;;"}
@@ -0,0 +1,35 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { Box, CircularProgress, Typography } from '@material-ui/core';
3
+
4
+ const LoadingState = ({
5
+ message = "Loading...",
6
+ size = 40
7
+ }) => {
8
+ return /* @__PURE__ */ jsxs(
9
+ Box,
10
+ {
11
+ display: "flex",
12
+ flexDirection: "column",
13
+ justifyContent: "center",
14
+ alignItems: "center",
15
+ p: 3,
16
+ role: "status",
17
+ "aria-label": message,
18
+ children: [
19
+ /* @__PURE__ */ jsx(CircularProgress, { size, "aria-hidden": "true" }),
20
+ message && /* @__PURE__ */ jsx(
21
+ Typography,
22
+ {
23
+ variant: "body2",
24
+ color: "textSecondary",
25
+ style: { marginTop: 16 },
26
+ children: message
27
+ }
28
+ )
29
+ ]
30
+ }
31
+ );
32
+ };
33
+
34
+ export { LoadingState };
35
+ //# sourceMappingURL=LoadingState.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoadingState.esm.js","sources":["../../../src/components/shared/LoadingState.tsx"],"sourcesContent":["import { Box, CircularProgress, Typography } from '@material-ui/core';\n\ninterface LoadingStateProps {\n message?: string;\n size?: number;\n}\n\nexport const LoadingState = ({\n message = 'Loading...',\n size = 40,\n}: LoadingStateProps) => {\n return (\n <Box\n display=\"flex\"\n flexDirection=\"column\"\n justifyContent=\"center\"\n alignItems=\"center\"\n p={3}\n role=\"status\"\n aria-label={message}\n >\n <CircularProgress size={size} aria-hidden=\"true\" />\n {message && (\n <Typography\n variant=\"body2\"\n color=\"textSecondary\"\n style={{ marginTop: 16 }}\n >\n {message}\n </Typography>\n )}\n </Box>\n );\n};\n"],"names":[],"mappings":";;;AAOO,MAAM,eAAe,CAAC;AAAA,EAC3B,OAAA,GAAU,YAAA;AAAA,EACV,IAAA,GAAO;AACT,CAAA,KAAyB;AACvB,EAAA,uBACE,IAAA;AAAA,IAAC,GAAA;AAAA,IAAA;AAAA,MACC,OAAA,EAAQ,MAAA;AAAA,MACR,aAAA,EAAc,QAAA;AAAA,MACd,cAAA,EAAe,QAAA;AAAA,MACf,UAAA,EAAW,QAAA;AAAA,MACX,CAAA,EAAG,CAAA;AAAA,MACH,IAAA,EAAK,QAAA;AAAA,MACL,YAAA,EAAY,OAAA;AAAA,MAEZ,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,gBAAA,EAAA,EAAiB,IAAA,EAAY,aAAA,EAAY,MAAA,EAAO,CAAA;AAAA,QAChD,OAAA,oBACC,GAAA;AAAA,UAAC,UAAA;AAAA,UAAA;AAAA,YACC,OAAA,EAAQ,OAAA;AAAA,YACR,KAAA,EAAM,eAAA;AAAA,YACN,KAAA,EAAO,EAAE,SAAA,EAAW,EAAA,EAAG;AAAA,YAEtB,QAAA,EAAA;AAAA;AAAA;AACH;AAAA;AAAA,GAEJ;AAEJ;;;;"}
@@ -0,0 +1,66 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { Box, Typography, IconButton } from '@material-ui/core';
3
+ import ChevronLeft from '@material-ui/icons/ChevronLeft';
4
+ import ChevronRight from '@material-ui/icons/ChevronRight';
5
+
6
+ const MiniPagination = ({
7
+ page,
8
+ totalPages,
9
+ totalItems,
10
+ onPrevious,
11
+ onNext,
12
+ itemLabel = "items"
13
+ }) => {
14
+ if (totalPages <= 1) return null;
15
+ return /* @__PURE__ */ jsxs(
16
+ Box,
17
+ {
18
+ display: "flex",
19
+ justifyContent: "space-between",
20
+ alignItems: "center",
21
+ p: 1,
22
+ borderTop: 1,
23
+ borderColor: "divider",
24
+ role: "navigation",
25
+ "aria-label": `Pagination for ${itemLabel}`,
26
+ children: [
27
+ /* @__PURE__ */ jsxs(Typography, { variant: "caption", color: "textSecondary", children: [
28
+ "Page ",
29
+ page + 1,
30
+ " of ",
31
+ totalPages,
32
+ " (",
33
+ totalItems,
34
+ " ",
35
+ itemLabel,
36
+ ")"
37
+ ] }),
38
+ /* @__PURE__ */ jsxs(Box, { children: [
39
+ /* @__PURE__ */ jsx(
40
+ IconButton,
41
+ {
42
+ size: "small",
43
+ onClick: onPrevious,
44
+ disabled: page === 0,
45
+ "aria-label": "Previous page",
46
+ children: /* @__PURE__ */ jsx(ChevronLeft, {})
47
+ }
48
+ ),
49
+ /* @__PURE__ */ jsx(
50
+ IconButton,
51
+ {
52
+ size: "small",
53
+ onClick: onNext,
54
+ disabled: page >= totalPages - 1,
55
+ "aria-label": "Next page",
56
+ children: /* @__PURE__ */ jsx(ChevronRight, {})
57
+ }
58
+ )
59
+ ] })
60
+ ]
61
+ }
62
+ );
63
+ };
64
+
65
+ export { MiniPagination };
66
+ //# sourceMappingURL=MiniPagination.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MiniPagination.esm.js","sources":["../../../src/components/shared/MiniPagination.tsx"],"sourcesContent":["import { Box, IconButton, Typography } from '@material-ui/core';\nimport ChevronLeft from '@material-ui/icons/ChevronLeft';\nimport ChevronRight from '@material-ui/icons/ChevronRight';\n\ninterface MiniPaginationProps {\n page: number;\n totalPages: number;\n totalItems: number;\n onPrevious: () => void;\n onNext: () => void;\n itemLabel?: string;\n}\n\nexport const MiniPagination = ({\n page,\n totalPages,\n totalItems,\n onPrevious,\n onNext,\n itemLabel = 'items',\n}: MiniPaginationProps) => {\n if (totalPages <= 1) return null;\n\n return (\n <Box\n display=\"flex\"\n justifyContent=\"space-between\"\n alignItems=\"center\"\n p={1}\n borderTop={1}\n borderColor=\"divider\"\n role=\"navigation\"\n aria-label={`Pagination for ${itemLabel}`}\n >\n <Typography variant=\"caption\" color=\"textSecondary\">\n Page {page + 1} of {totalPages} ({totalItems} {itemLabel})\n </Typography>\n <Box>\n <IconButton\n size=\"small\"\n onClick={onPrevious}\n disabled={page === 0}\n aria-label=\"Previous page\"\n >\n <ChevronLeft />\n </IconButton>\n <IconButton\n size=\"small\"\n onClick={onNext}\n disabled={page >= totalPages - 1}\n aria-label=\"Next page\"\n >\n <ChevronRight />\n </IconButton>\n </Box>\n </Box>\n );\n};\n"],"names":[],"mappings":";;;;;AAaO,MAAM,iBAAiB,CAAC;AAAA,EAC7B,IAAA;AAAA,EACA,UAAA;AAAA,EACA,UAAA;AAAA,EACA,UAAA;AAAA,EACA,MAAA;AAAA,EACA,SAAA,GAAY;AACd,CAAA,KAA2B;AACzB,EAAA,IAAI,UAAA,IAAc,GAAG,OAAO,IAAA;AAE5B,EAAA,uBACE,IAAA;AAAA,IAAC,GAAA;AAAA,IAAA;AAAA,MACC,OAAA,EAAQ,MAAA;AAAA,MACR,cAAA,EAAe,eAAA;AAAA,MACf,UAAA,EAAW,QAAA;AAAA,MACX,CAAA,EAAG,CAAA;AAAA,MACH,SAAA,EAAW,CAAA;AAAA,MACX,WAAA,EAAY,SAAA;AAAA,MACZ,IAAA,EAAK,YAAA;AAAA,MACL,YAAA,EAAY,kBAAkB,SAAS,CAAA,CAAA;AAAA,MAEvC,QAAA,EAAA;AAAA,wBAAA,IAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,SAAA,EAAU,KAAA,EAAM,eAAA,EAAgB,QAAA,EAAA;AAAA,UAAA,OAAA;AAAA,UAC5C,IAAA,GAAO,CAAA;AAAA,UAAE,MAAA;AAAA,UAAK,UAAA;AAAA,UAAW,IAAA;AAAA,UAAG,UAAA;AAAA,UAAW,GAAA;AAAA,UAAE,SAAA;AAAA,UAAU;AAAA,SAAA,EAC3D,CAAA;AAAA,6BACC,GAAA,EAAA,EACC,QAAA,EAAA;AAAA,0BAAA,GAAA;AAAA,YAAC,UAAA;AAAA,YAAA;AAAA,cACC,IAAA,EAAK,OAAA;AAAA,cACL,OAAA,EAAS,UAAA;AAAA,cACT,UAAU,IAAA,KAAS,CAAA;AAAA,cACnB,YAAA,EAAW,eAAA;AAAA,cAEX,8BAAC,WAAA,EAAA,EAAY;AAAA;AAAA,WACf;AAAA,0BACA,GAAA;AAAA,YAAC,UAAA;AAAA,YAAA;AAAA,cACC,IAAA,EAAK,OAAA;AAAA,cACL,OAAA,EAAS,MAAA;AAAA,cACT,QAAA,EAAU,QAAQ,UAAA,GAAa,CAAA;AAAA,cAC/B,YAAA,EAAW,WAAA;AAAA,cAEX,8BAAC,YAAA,EAAA,EAAa;AAAA;AAAA;AAChB,SAAA,EACF;AAAA;AAAA;AAAA,GACF;AAEJ;;;;"}
@@ -0,0 +1,54 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { TextField, InputAdornment } from '@material-ui/core';
3
+ import { makeStyles } from '@material-ui/core/styles';
4
+ import SearchIcon from '@material-ui/icons/Search';
5
+ import ClearIcon from '@material-ui/icons/Clear';
6
+ import IconButton from '@material-ui/core/IconButton';
7
+
8
+ const useStyles = makeStyles(() => ({
9
+ root: {
10
+ minWidth: 200
11
+ },
12
+ clearButton: {
13
+ padding: 4
14
+ }
15
+ }));
16
+ const SearchInput = ({
17
+ value,
18
+ onChange,
19
+ placeholder = "Search flags..."
20
+ }) => {
21
+ const classes = useStyles();
22
+ const handleClear = () => onChange("");
23
+ return /* @__PURE__ */ jsx(
24
+ TextField,
25
+ {
26
+ className: classes.root,
27
+ variant: "outlined",
28
+ size: "small",
29
+ placeholder,
30
+ value,
31
+ onChange: (e) => onChange(e.target.value),
32
+ inputProps: {
33
+ "aria-label": placeholder,
34
+ role: "searchbox"
35
+ },
36
+ InputProps: {
37
+ startAdornment: /* @__PURE__ */ jsx(InputAdornment, { position: "start", children: /* @__PURE__ */ jsx(SearchIcon, { color: "action", "aria-hidden": "true" }) }),
38
+ endAdornment: value ? /* @__PURE__ */ jsx(InputAdornment, { position: "end", children: /* @__PURE__ */ jsx(
39
+ IconButton,
40
+ {
41
+ className: classes.clearButton,
42
+ onClick: handleClear,
43
+ size: "small",
44
+ "aria-label": "Clear search",
45
+ children: /* @__PURE__ */ jsx(ClearIcon, { fontSize: "small" })
46
+ }
47
+ ) }) : null
48
+ }
49
+ }
50
+ );
51
+ };
52
+
53
+ export { SearchInput };
54
+ //# sourceMappingURL=SearchInput.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SearchInput.esm.js","sources":["../../../src/components/shared/SearchInput.tsx"],"sourcesContent":["import { TextField, InputAdornment } from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport SearchIcon from '@material-ui/icons/Search';\nimport ClearIcon from '@material-ui/icons/Clear';\nimport IconButton from '@material-ui/core/IconButton';\n\nconst useStyles = makeStyles(() => ({\n root: {\n minWidth: 200,\n },\n clearButton: {\n padding: 4,\n },\n}));\n\ninterface SearchInputProps {\n value: string;\n onChange: (value: string) => void;\n placeholder?: string;\n}\n\n/**\n * Reusable search input component\n */\nexport const SearchInput = ({\n value,\n onChange,\n placeholder = 'Search flags...',\n}: SearchInputProps) => {\n const classes = useStyles();\n\n const handleClear = () => onChange('');\n\n return (\n <TextField\n className={classes.root}\n variant=\"outlined\"\n size=\"small\"\n placeholder={placeholder}\n value={value}\n onChange={e => onChange(e.target.value)}\n inputProps={{\n 'aria-label': placeholder,\n role: 'searchbox',\n }}\n InputProps={{\n startAdornment: (\n <InputAdornment position=\"start\">\n <SearchIcon color=\"action\" aria-hidden=\"true\" />\n </InputAdornment>\n ),\n endAdornment: value ? (\n <InputAdornment position=\"end\">\n <IconButton\n className={classes.clearButton}\n onClick={handleClear}\n size=\"small\"\n aria-label=\"Clear search\"\n >\n <ClearIcon fontSize=\"small\" />\n </IconButton>\n </InputAdornment>\n ) : null,\n }}\n />\n );\n};\n"],"names":[],"mappings":";;;;;;;AAMA,MAAM,SAAA,GAAY,WAAW,OAAO;AAAA,EAClC,IAAA,EAAM;AAAA,IACJ,QAAA,EAAU;AAAA,GACZ;AAAA,EACA,WAAA,EAAa;AAAA,IACX,OAAA,EAAS;AAAA;AAEb,CAAA,CAAE,CAAA;AAWK,MAAM,cAAc,CAAC;AAAA,EAC1B,KAAA;AAAA,EACA,QAAA;AAAA,EACA,WAAA,GAAc;AAChB,CAAA,KAAwB;AACtB,EAAA,MAAM,UAAU,SAAA,EAAU;AAE1B,EAAA,MAAM,WAAA,GAAc,MAAM,QAAA,CAAS,EAAE,CAAA;AAErC,EAAA,uBACE,GAAA;AAAA,IAAC,SAAA;AAAA,IAAA;AAAA,MACC,WAAW,OAAA,CAAQ,IAAA;AAAA,MACnB,OAAA,EAAQ,UAAA;AAAA,MACR,IAAA,EAAK,OAAA;AAAA,MACL,WAAA;AAAA,MACA,KAAA;AAAA,MACA,QAAA,EAAU,CAAA,CAAA,KAAK,QAAA,CAAS,CAAA,CAAE,OAAO,KAAK,CAAA;AAAA,MACtC,UAAA,EAAY;AAAA,QACV,YAAA,EAAc,WAAA;AAAA,QACd,IAAA,EAAM;AAAA,OACR;AAAA,MACA,UAAA,EAAY;AAAA,QACV,cAAA,kBACE,GAAA,CAAC,cAAA,EAAA,EAAe,QAAA,EAAS,OAAA,EACvB,QAAA,kBAAA,GAAA,CAAC,UAAA,EAAA,EAAW,KAAA,EAAM,QAAA,EAAS,aAAA,EAAY,MAAA,EAAO,CAAA,EAChD,CAAA;AAAA,QAEF,YAAA,EAAc,KAAA,mBACZ,GAAA,CAAC,cAAA,EAAA,EAAe,UAAS,KAAA,EACvB,QAAA,kBAAA,GAAA;AAAA,UAAC,UAAA;AAAA,UAAA;AAAA,YACC,WAAW,OAAA,CAAQ,WAAA;AAAA,YACnB,OAAA,EAAS,WAAA;AAAA,YACT,IAAA,EAAK,OAAA;AAAA,YACL,YAAA,EAAW,cAAA;AAAA,YAEX,QAAA,kBAAA,GAAA,CAAC,SAAA,EAAA,EAAU,QAAA,EAAS,OAAA,EAAQ;AAAA;AAAA,WAEhC,CAAA,GACE;AAAA;AACN;AAAA,GACF;AAEJ;;;;"}
@@ -0,0 +1,38 @@
1
+ const FEATURE_TYPES = {
2
+ CONFIG: "CONFIG"};
3
+ const MAX_DISPLAY_TAGS = 3;
4
+ const MAX_TABLE_ENVIRONMENTS = 6;
5
+ const MAX_DETAIL_ENVIRONMENTS = 10;
6
+ const DESCRIPTION_TRUNCATE_LENGTH = 60;
7
+ const PAGINATION_OPTIONS = [10, 25, 50, 100];
8
+ const DEFAULT_ROWS_PER_PAGE = 50;
9
+ const CHART_CONFIG = {
10
+ HEIGHT: 250,
11
+ MARGIN: { top: 5, right: 30, left: 0, bottom: 5 }
12
+ };
13
+ const ENV_COLORS = {
14
+ development: "#4caf50",
15
+ dev: "#4caf50",
16
+ staging: "#ff9800",
17
+ stage: "#ff9800",
18
+ production: "#f44336",
19
+ prod: "#f44336"
20
+ };
21
+ const DEFAULT_ENV_COLORS = [
22
+ "#2196f3",
23
+ "#9c27b0",
24
+ "#00bcd4",
25
+ "#795548",
26
+ "#607d8b",
27
+ "#e91e63"
28
+ ];
29
+ const getEnvColor = (envName, index) => {
30
+ const lowerName = envName.toLowerCase();
31
+ for (const [key, color] of Object.entries(ENV_COLORS)) {
32
+ if (lowerName.includes(key)) return color;
33
+ }
34
+ return DEFAULT_ENV_COLORS[index % DEFAULT_ENV_COLORS.length] || "#2196f3";
35
+ };
36
+
37
+ export { CHART_CONFIG, DEFAULT_ENV_COLORS, DEFAULT_ROWS_PER_PAGE, DESCRIPTION_TRUNCATE_LENGTH, ENV_COLORS, FEATURE_TYPES, MAX_DETAIL_ENVIRONMENTS, MAX_DISPLAY_TAGS, MAX_TABLE_ENVIRONMENTS, PAGINATION_OPTIONS, getEnvColor };
38
+ //# sourceMappingURL=index.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.esm.js","sources":["../../src/constants/index.ts"],"sourcesContent":["/**\n * Constants for FlagsTab and related components\n */\n\n/** Feature types from Flagsmith API */\nexport const FEATURE_TYPES = {\n CONFIG: 'CONFIG',\n FLAG: 'FLAG',\n} as const;\n\n/** Maximum number of tags to display inline before showing \"+N more\" */\nexport const MAX_DISPLAY_TAGS = 3;\n\n/** Maximum number of environments to show in the main table columns */\nexport const MAX_TABLE_ENVIRONMENTS = 6;\n\n/** Maximum number of environments to show in the detailed environment table */\nexport const MAX_DETAIL_ENVIRONMENTS = 10;\n\n/** Maximum characters for description truncation */\nexport const DESCRIPTION_TRUNCATE_LENGTH = 60;\n\n/** Pagination options for the flags table */\nexport const PAGINATION_OPTIONS = [10, 25, 50, 100];\n\n/** Default rows per page */\nexport const DEFAULT_ROWS_PER_PAGE = 50;\n\n/** Chart dimensions */\nexport const CHART_CONFIG = {\n HEIGHT: 250,\n MARGIN: { top: 5, right: 30, left: 0, bottom: 5 },\n} as const;\n\n/** Environment colors for analytics chart */\nexport const ENV_COLORS: Record<string, string> = {\n development: '#4caf50',\n dev: '#4caf50',\n staging: '#ff9800',\n stage: '#ff9800',\n production: '#f44336',\n prod: '#f44336',\n};\n\n/** Fallback colors for environments not matching predefined names */\nexport const DEFAULT_ENV_COLORS = [\n '#2196f3',\n '#9c27b0',\n '#00bcd4',\n '#795548',\n '#607d8b',\n '#e91e63',\n] as const;\n\n/**\n * Get color for an environment based on its name\n */\nexport const getEnvColor = (envName: string, index: number): string => {\n const lowerName = envName.toLowerCase();\n for (const [key, color] of Object.entries(ENV_COLORS)) {\n if (lowerName.includes(key)) return color;\n }\n return DEFAULT_ENV_COLORS[index % DEFAULT_ENV_COLORS.length] || '#2196f3';\n};\n"],"names":[],"mappings":"AAKO,MAAM,aAAA,GAAgB;AAAA,EAC3B,MAAA,EAAQ,QAEV;AAGO,MAAM,gBAAA,GAAmB;AAGzB,MAAM,sBAAA,GAAyB;AAG/B,MAAM,uBAAA,GAA0B;AAGhC,MAAM,2BAAA,GAA8B;AAGpC,MAAM,kBAAA,GAAqB,CAAC,EAAA,EAAI,EAAA,EAAI,IAAI,GAAG;AAG3C,MAAM,qBAAA,GAAwB;AAG9B,MAAM,YAAA,GAAe;AAAA,EAC1B,MAAA,EAAQ,GAAA;AAAA,EACR,MAAA,EAAQ,EAAE,GAAA,EAAK,CAAA,EAAG,OAAO,EAAA,EAAI,IAAA,EAAM,CAAA,EAAG,MAAA,EAAQ,CAAA;AAChD;AAGO,MAAM,UAAA,GAAqC;AAAA,EAChD,WAAA,EAAa,SAAA;AAAA,EACb,GAAA,EAAK,SAAA;AAAA,EACL,OAAA,EAAS,SAAA;AAAA,EACT,KAAA,EAAO,SAAA;AAAA,EACP,UAAA,EAAY,SAAA;AAAA,EACZ,IAAA,EAAM;AACR;AAGO,MAAM,kBAAA,GAAqB;AAAA,EAChC,SAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA;AACF;AAKO,MAAM,WAAA,GAAc,CAAC,OAAA,EAAiB,KAAA,KAA0B;AACrE,EAAA,MAAM,SAAA,GAAY,QAAQ,WAAA,EAAY;AACtC,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,UAAU,CAAA,EAAG;AACrD,IAAA,IAAI,SAAA,CAAU,QAAA,CAAS,GAAG,CAAA,EAAG,OAAO,KAAA;AAAA,EACtC;AACA,EAAA,OAAO,kBAAA,CAAmB,KAAA,GAAQ,kBAAA,CAAmB,MAAM,CAAA,IAAK,SAAA;AAClE;;;;"}