@mittwald/flow-react-components 1.3.0-next.21 → 1.3.0-next.23

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 (27) hide show
  1. package/dist/assets/component-index.json +1 -1
  2. package/dist/assets/doc-properties.json +1 -1
  3. package/dist/css/all-layered.css +1 -1
  4. package/dist/css/all.css +1 -1
  5. package/dist/js/packages/components/src/components/CartesianChart/components/Area/Area.mjs +4 -1
  6. package/dist/js/packages/components/src/components/CartesianChart/components/Area/Area.mjs.map +1 -1
  7. package/dist/js/packages/components/src/components/CartesianChart/components/Bar/Bar.mjs +4 -1
  8. package/dist/js/packages/components/src/components/CartesianChart/components/Bar/Bar.mjs.map +1 -1
  9. package/dist/js/packages/components/src/components/CartesianChart/components/Line/Line.mjs +4 -1
  10. package/dist/js/packages/components/src/components/CartesianChart/components/Line/Line.mjs.map +1 -1
  11. package/dist/js/packages/components/src/components/CartesianChart/hooks/useChartAnimation.mjs +27 -0
  12. package/dist/js/packages/components/src/components/CartesianChart/hooks/useChartAnimation.mjs.map +1 -0
  13. package/dist/js/packages/components/src/components/DonutChart/DonutChart.module.mjs +6 -3
  14. package/dist/js/packages/components/src/components/DonutChart/DonutChart.module.mjs.map +1 -1
  15. package/dist/js/packages/components/src/components/DonutChart/components/DonutChartFill.mjs +13 -2
  16. package/dist/js/packages/components/src/components/DonutChart/components/DonutChartFill.mjs.map +1 -1
  17. package/dist/js/packages/components/src/components/Popover/Popover.module.mjs.map +1 -1
  18. package/dist/js/packages/components/src/components/Popover/components/NonModalPopoverContent/NonModalPopoverContent.mjs.map +1 -1
  19. package/dist/js/packages/components/src/components/ProgressBar/ProgressBar.module.mjs +1 -0
  20. package/dist/js/packages/components/src/components/ProgressBar/ProgressBar.module.mjs.map +1 -1
  21. package/dist/js/packages/design-tokens/dist/json-runtime/all-dark.mjs +12 -0
  22. package/dist/js/packages/design-tokens/dist/json-runtime/all-dark.mjs.map +1 -1
  23. package/dist/js/packages/design-tokens/dist/json-runtime/all-light.mjs +12 -0
  24. package/dist/js/packages/design-tokens/dist/json-runtime/all-light.mjs.map +1 -1
  25. package/dist/types/components/CartesianChart/hooks/useChartAnimation.d.ts +1 -0
  26. package/dist/types/lib/theming/hooks/useDesignTokens.d.ts +14 -0
  27. package/package.json +9 -9
@@ -5,6 +5,7 @@ import { AreaDot } from "../AreaDot/AreaDot.mjs";
5
5
  import { isCategoricalColor } from "../../../../lib/tokens/isCategoricalColor.mjs";
6
6
  import { isDataKeyWithLabel } from "../../types.mjs";
7
7
  import { useScopedStackId } from "../../hooks/useScopedStackId.mjs";
8
+ import { useChartAnimation } from "../../hooks/useChartAnimation.mjs";
8
9
  import "react";
9
10
  import { jsx } from "react/jsx-runtime";
10
11
  import * as Recharts from "recharts";
@@ -14,6 +15,7 @@ var Area = (props) => {
14
15
  const { color: colorFromProps = "sea-green", stackId: stackIdFromProps = 1, fillOpacity = 1, ...rest } = props;
15
16
  const tokens = useDesignTokens();
16
17
  const stackId = useScopedStackId(stackIdFromProps);
18
+ const animation = useChartAnimation();
17
19
  const color = isCategoricalColor(colorFromProps) ? `var(--color--categorical--${colorFromProps})` : colorFromProps;
18
20
  return /* @__PURE__ */ jsx(Recharts.Area, {
19
21
  name: isDataKeyWithLabel(props) ? props.dataKeyLabel : props.dataKey,
@@ -23,7 +25,8 @@ var Area = (props) => {
23
25
  activeDot: /* @__PURE__ */ jsx(AreaDot, { color }),
24
26
  fill: color,
25
27
  stroke: tokens.area["border-color"].value,
26
- strokeWidth: tokens.area["border-width"].value
28
+ strokeWidth: tokens.area["border-width"].value,
29
+ ...animation
27
30
  });
28
31
  };
29
32
  var TypedArea = () => Area;
@@ -1 +1 @@
1
- {"version":3,"file":"Area.mjs","names":[],"sources":["../../../../../../../../../src/components/CartesianChart/components/Area/Area.tsx"],"sourcesContent":["import { type ComponentType, type FC } from \"react\";\nimport * as Recharts from \"recharts\";\nimport { AreaDot } from \"../AreaDot\";\nimport type { CategoricalWithCustomColor } from \"@/lib/tokens/CategoricalColors\";\nimport { isCategoricalColor } from \"@/lib/tokens/isCategoricalColor\";\nimport {\n type ChartDataValue,\n type DataKeyProp,\n type DataKeyWithLabel,\n isDataKeyWithLabel,\n} from \"@/components/CartesianChart/types\";\nimport { useScopedStackId } from \"@/components/CartesianChart/hooks/useScopedStackId\";\nimport { useDesignTokens } from \"@/lib/theming\";\n\ntype AreaBaseProps = Pick<\n Recharts.AreaProps,\n | \"className\"\n | \"stackId\"\n | \"fillOpacity\"\n | \"key\"\n | \"xAxisId\"\n | \"yAxisId\"\n | \"type\"\n | \"unit\"\n> & {\n /** The color of the area. @default \"sea-green\" */\n color?: CategoricalWithCustomColor;\n};\n\nexport interface AreaPropsByDataKeyProp<\n TData extends ChartDataValue = ChartDataValue,\n> extends AreaBaseProps {\n dataKey: DataKeyProp<TData>;\n}\n\nexport interface AreaPropsByDataKey<\n TData extends ChartDataValue = ChartDataValue,\n>\n extends AreaBaseProps, DataKeyWithLabel<TData> {}\n\nexport type AreaProps<TData extends ChartDataValue = ChartDataValue> =\n AreaPropsByDataKey<TData> | AreaPropsByDataKeyProp<TData>;\n\n/** @flr-generate all */\nexport const Area: FC<AreaProps> = (props) => {\n const {\n color: colorFromProps = \"sea-green\",\n stackId: stackIdFromProps = 1,\n fillOpacity = 1,\n ...rest\n } = props;\n\n const tokens = useDesignTokens();\n const stackId = useScopedStackId(stackIdFromProps);\n\n const color = isCategoricalColor(colorFromProps)\n ? `var(--color--categorical--${colorFromProps})`\n : colorFromProps;\n\n return (\n <Recharts.Area\n name={isDataKeyWithLabel(props) ? props.dataKeyLabel : props.dataKey}\n stackId={stackId}\n fillOpacity={fillOpacity}\n {...rest}\n activeDot={<AreaDot color={color} />}\n fill={color}\n stroke={tokens.area[\"border-color\"].value}\n strokeWidth={tokens.area[\"border-width\"].value}\n />\n );\n};\n\nexport const TypedArea = <TData extends ChartDataValue = ChartDataValue>() =>\n Area as ComponentType<AreaPropsByDataKeyProp<TData>>;\n\nexport default Area;\n"],"mappings":";;;;;;;;;;;;AA4CA,IAAa,QAAuB,UAAU;CAC5C,MAAM,EACJ,OAAO,iBAAiB,aACxB,SAAS,mBAAmB,GAC5B,cAAc,GACd,GAAG,SACD;CAEJ,MAAM,SAAS,gBAAgB;CAC/B,MAAM,UAAU,iBAAiB,gBAAgB;CAEjD,MAAM,QAAQ,mBAAmB,cAAc,IAC3C,6BAA6B,eAAe,KAC5C;CAEJ,OACE,oBAAC,SAAS,MAAV;EACE,MAAM,mBAAmB,KAAK,IAAI,MAAM,eAAe,MAAM;EACpD;EACI;EACb,GAAI;EACJ,WAAW,oBAAC,SAAD,EAAgB,MAAQ,CAAA;EACnC,MAAM;EACN,QAAQ,OAAO,KAAK,eAAe,CAAC;EACpC,aAAa,OAAO,KAAK,eAAe,CAAC;CAC1C,CAAA;AAEL;AAEA,IAAa,kBACX"}
1
+ {"version":3,"file":"Area.mjs","names":[],"sources":["../../../../../../../../../src/components/CartesianChart/components/Area/Area.tsx"],"sourcesContent":["import { type ComponentType, type FC } from \"react\";\nimport * as Recharts from \"recharts\";\nimport { AreaDot } from \"../AreaDot\";\nimport type { CategoricalWithCustomColor } from \"@/lib/tokens/CategoricalColors\";\nimport { isCategoricalColor } from \"@/lib/tokens/isCategoricalColor\";\nimport {\n type ChartDataValue,\n type DataKeyProp,\n type DataKeyWithLabel,\n isDataKeyWithLabel,\n} from \"@/components/CartesianChart/types\";\nimport { useScopedStackId } from \"@/components/CartesianChart/hooks/useScopedStackId\";\nimport { useChartAnimation } from \"@/components/CartesianChart/hooks/useChartAnimation\";\nimport { useDesignTokens } from \"@/lib/theming\";\n\ntype AreaBaseProps = Pick<\n Recharts.AreaProps,\n | \"className\"\n | \"stackId\"\n | \"fillOpacity\"\n | \"key\"\n | \"xAxisId\"\n | \"yAxisId\"\n | \"type\"\n | \"unit\"\n> & {\n /** The color of the area. @default \"sea-green\" */\n color?: CategoricalWithCustomColor;\n};\n\nexport interface AreaPropsByDataKeyProp<\n TData extends ChartDataValue = ChartDataValue,\n> extends AreaBaseProps {\n dataKey: DataKeyProp<TData>;\n}\n\nexport interface AreaPropsByDataKey<\n TData extends ChartDataValue = ChartDataValue,\n>\n extends AreaBaseProps, DataKeyWithLabel<TData> {}\n\nexport type AreaProps<TData extends ChartDataValue = ChartDataValue> =\n AreaPropsByDataKey<TData> | AreaPropsByDataKeyProp<TData>;\n\n/** @flr-generate all */\nexport const Area: FC<AreaProps> = (props) => {\n const {\n color: colorFromProps = \"sea-green\",\n stackId: stackIdFromProps = 1,\n fillOpacity = 1,\n ...rest\n } = props;\n\n const tokens = useDesignTokens();\n const stackId = useScopedStackId(stackIdFromProps);\n const animation = useChartAnimation();\n\n const color = isCategoricalColor(colorFromProps)\n ? `var(--color--categorical--${colorFromProps})`\n : colorFromProps;\n\n return (\n <Recharts.Area\n name={isDataKeyWithLabel(props) ? props.dataKeyLabel : props.dataKey}\n stackId={stackId}\n fillOpacity={fillOpacity}\n {...rest}\n activeDot={<AreaDot color={color} />}\n fill={color}\n stroke={tokens.area[\"border-color\"].value}\n strokeWidth={tokens.area[\"border-width\"].value}\n {...animation}\n />\n );\n};\n\nexport const TypedArea = <TData extends ChartDataValue = ChartDataValue>() =>\n Area as ComponentType<AreaPropsByDataKeyProp<TData>>;\n\nexport default Area;\n"],"mappings":";;;;;;;;;;;;;AA6CA,IAAa,QAAuB,UAAU;CAC5C,MAAM,EACJ,OAAO,iBAAiB,aACxB,SAAS,mBAAmB,GAC5B,cAAc,GACd,GAAG,SACD;CAEJ,MAAM,SAAS,gBAAgB;CAC/B,MAAM,UAAU,iBAAiB,gBAAgB;CACjD,MAAM,YAAY,kBAAkB;CAEpC,MAAM,QAAQ,mBAAmB,cAAc,IAC3C,6BAA6B,eAAe,KAC5C;CAEJ,OACE,oBAAC,SAAS,MAAV;EACE,MAAM,mBAAmB,KAAK,IAAI,MAAM,eAAe,MAAM;EACpD;EACI;EACb,GAAI;EACJ,WAAW,oBAAC,SAAD,EAAgB,MAAQ,CAAA;EACnC,MAAM;EACN,QAAQ,OAAO,KAAK,eAAe,CAAC;EACpC,aAAa,OAAO,KAAK,eAAe,CAAC;EACzC,GAAI;CACL,CAAA;AAEL;AAEA,IAAa,kBACX"}
@@ -5,6 +5,7 @@ import { useCartesianChartContext } from "../../context.mjs";
5
5
  import { isCategoricalColor } from "../../../../lib/tokens/isCategoricalColor.mjs";
6
6
  import { isDataKeyWithLabel } from "../../types.mjs";
7
7
  import { useScopedStackId } from "../../hooks/useScopedStackId.mjs";
8
+ import { useChartAnimation } from "../../hooks/useChartAnimation.mjs";
8
9
  import "react";
9
10
  import { jsx } from "react/jsx-runtime";
10
11
  import * as Recharts from "recharts";
@@ -13,6 +14,7 @@ import * as Recharts from "recharts";
13
14
  var Bar = (props) => {
14
15
  const { color: colorFromProps = "sea-green", ...rest } = props;
15
16
  const tokens = useDesignTokens();
17
+ const animation = useChartAnimation();
16
18
  const { layout } = useCartesianChartContext();
17
19
  const stackId = useScopedStackId(props.stackId);
18
20
  const color = isCategoricalColor(colorFromProps) ? `var(--color--categorical--${colorFromProps})` : colorFromProps;
@@ -33,7 +35,8 @@ var Bar = (props) => {
33
35
  ...rest,
34
36
  stackId,
35
37
  fill: color,
36
- radius: stackId === void 0 ? radius : 0
38
+ radius: stackId === void 0 ? radius : 0,
39
+ ...animation
37
40
  });
38
41
  if (stackId === void 0) return bar;
39
42
  return /* @__PURE__ */ jsx(Recharts.BarStack, {
@@ -1 +1 @@
1
- {"version":3,"file":"Bar.mjs","names":[],"sources":["../../../../../../../../../src/components/CartesianChart/components/Bar/Bar.tsx"],"sourcesContent":["import { type ComponentType, type FC } from \"react\";\nimport * as Recharts from \"recharts\";\nimport type { CategoricalWithCustomColor } from \"@/lib/tokens/CategoricalColors\";\nimport { isCategoricalColor } from \"@/lib/tokens/isCategoricalColor\";\nimport {\n type ChartDataValue,\n type DataKeyProp,\n type DataKeyWithLabel,\n isDataKeyWithLabel,\n} from \"@/components/CartesianChart/types\";\nimport { useCartesianChartContext } from \"@/components/CartesianChart/context\";\nimport { useScopedStackId } from \"@/components/CartesianChart/hooks/useScopedStackId\";\nimport { useDesignTokens } from \"@/lib/theming\";\n\ntype BarBaseProps = Pick<\n Recharts.BarProps,\n | \"className\"\n | \"stackId\"\n | \"key\"\n | \"xAxisId\"\n | \"yAxisId\"\n | \"unit\"\n | \"barSize\"\n | \"maxBarSize\"\n | \"minPointSize\"\n> & {\n /** The color of the bar. @default \"sea-green\" */\n color?: CategoricalWithCustomColor;\n};\n\nexport interface BarPropsByDataKeyProp<\n TData extends ChartDataValue = ChartDataValue,\n> extends BarBaseProps {\n dataKey: DataKeyProp<TData>;\n}\n\nexport interface BarPropsByDataKey<\n TData extends ChartDataValue = ChartDataValue,\n>\n extends BarBaseProps, DataKeyWithLabel<TData> {}\n\nexport type BarProps<TData extends ChartDataValue = ChartDataValue> =\n BarPropsByDataKey<TData> | BarPropsByDataKeyProp<TData>;\n\n/** @flr-generate all */\nexport const Bar: FC<BarProps> = (props) => {\n const { color: colorFromProps = \"sea-green\", ...rest } = props;\n\n const tokens = useDesignTokens();\n const { layout } = useCartesianChartContext();\n const stackId = useScopedStackId(props.stackId);\n\n const color = isCategoricalColor(colorFromProps)\n ? `var(--color--categorical--${colorFromProps})`\n : colorFromProps;\n\n const cornerRadius = parseInt(tokens.bar[\"corner-radius\"].value);\n const radius: Recharts.BarProps[\"radius\"] =\n layout === \"vertical\"\n ? [0, cornerRadius, cornerRadius, 0]\n : [cornerRadius, cornerRadius, 0, 0];\n\n const bar = (\n <Recharts.Bar\n name={isDataKeyWithLabel(props) ? props.dataKeyLabel : props.dataKey}\n {...rest}\n stackId={stackId}\n fill={color}\n radius={stackId === undefined ? radius : 0}\n />\n );\n\n if (stackId === undefined) {\n return bar;\n }\n\n // Every Bar of a stack renders its own BarStack, because a Bar cannot know\n // its siblings — they all describe the same clip path, so the duplicates are\n // redundant rather than conflicting.\n return (\n <Recharts.BarStack stackId={stackId} radius={radius}>\n {bar}\n </Recharts.BarStack>\n );\n};\n\nexport const TypedBar = <TData extends ChartDataValue = ChartDataValue>() =>\n Bar as ComponentType<BarPropsByDataKeyProp<TData>>;\n\nexport default Bar;\n"],"mappings":";;;;;;;;;;;;AA6CA,IAAa,OAAqB,UAAU;CAC1C,MAAM,EAAE,OAAO,iBAAiB,aAAa,GAAG,SAAS;CAEzD,MAAM,SAAS,gBAAgB;CAC/B,MAAM,EAAE,WAAW,yBAAyB;CAC5C,MAAM,UAAU,iBAAiB,MAAM,OAAO;CAE9C,MAAM,QAAQ,mBAAmB,cAAc,IAC3C,6BAA6B,eAAe,KAC5C;CAEJ,MAAM,eAAe,SAAS,OAAO,IAAI,gBAAgB,CAAC,KAAK;CAC/D,MAAM,SACJ,WAAW,aACP;EAAC;EAAG;EAAc;EAAc;CAAC,IACjC;EAAC;EAAc;EAAc;EAAG;CAAC;CAEvC,MAAM,MACJ,oBAAC,SAAS,KAAV;EACE,MAAM,mBAAmB,KAAK,IAAI,MAAM,eAAe,MAAM;EAC7D,GAAI;EACK;EACT,MAAM;EACN,QAAQ,YAAY,KAAA,IAAY,SAAS;CAC1C,CAAA;CAGH,IAAI,YAAY,KAAA,GACd,OAAO;CAMT,OACE,oBAAC,SAAS,UAAV;EAA4B;EAAiB;EAC1C,UAAA;CACgB,CAAA;AAEvB;AAEA,IAAa,iBACX"}
1
+ {"version":3,"file":"Bar.mjs","names":[],"sources":["../../../../../../../../../src/components/CartesianChart/components/Bar/Bar.tsx"],"sourcesContent":["import { type ComponentType, type FC } from \"react\";\nimport * as Recharts from \"recharts\";\nimport type { CategoricalWithCustomColor } from \"@/lib/tokens/CategoricalColors\";\nimport { isCategoricalColor } from \"@/lib/tokens/isCategoricalColor\";\nimport {\n type ChartDataValue,\n type DataKeyProp,\n type DataKeyWithLabel,\n isDataKeyWithLabel,\n} from \"@/components/CartesianChart/types\";\nimport { useCartesianChartContext } from \"@/components/CartesianChart/context\";\nimport { useScopedStackId } from \"@/components/CartesianChart/hooks/useScopedStackId\";\nimport { useChartAnimation } from \"@/components/CartesianChart/hooks/useChartAnimation\";\nimport { useDesignTokens } from \"@/lib/theming\";\n\ntype BarBaseProps = Pick<\n Recharts.BarProps,\n | \"className\"\n | \"stackId\"\n | \"key\"\n | \"xAxisId\"\n | \"yAxisId\"\n | \"unit\"\n | \"barSize\"\n | \"maxBarSize\"\n | \"minPointSize\"\n> & {\n /** The color of the bar. @default \"sea-green\" */\n color?: CategoricalWithCustomColor;\n};\n\nexport interface BarPropsByDataKeyProp<\n TData extends ChartDataValue = ChartDataValue,\n> extends BarBaseProps {\n dataKey: DataKeyProp<TData>;\n}\n\nexport interface BarPropsByDataKey<\n TData extends ChartDataValue = ChartDataValue,\n>\n extends BarBaseProps, DataKeyWithLabel<TData> {}\n\nexport type BarProps<TData extends ChartDataValue = ChartDataValue> =\n BarPropsByDataKey<TData> | BarPropsByDataKeyProp<TData>;\n\n/** @flr-generate all */\nexport const Bar: FC<BarProps> = (props) => {\n const { color: colorFromProps = \"sea-green\", ...rest } = props;\n\n const tokens = useDesignTokens();\n const animation = useChartAnimation();\n const { layout } = useCartesianChartContext();\n const stackId = useScopedStackId(props.stackId);\n\n const color = isCategoricalColor(colorFromProps)\n ? `var(--color--categorical--${colorFromProps})`\n : colorFromProps;\n\n const cornerRadius = parseInt(tokens.bar[\"corner-radius\"].value);\n const radius: Recharts.BarProps[\"radius\"] =\n layout === \"vertical\"\n ? [0, cornerRadius, cornerRadius, 0]\n : [cornerRadius, cornerRadius, 0, 0];\n\n const bar = (\n <Recharts.Bar\n name={isDataKeyWithLabel(props) ? props.dataKeyLabel : props.dataKey}\n {...rest}\n stackId={stackId}\n fill={color}\n radius={stackId === undefined ? radius : 0}\n {...animation}\n />\n );\n\n if (stackId === undefined) {\n return bar;\n }\n\n // Every Bar of a stack renders its own BarStack, because a Bar cannot know\n // its siblings — they all describe the same clip path, so the duplicates are\n // redundant rather than conflicting.\n return (\n <Recharts.BarStack stackId={stackId} radius={radius}>\n {bar}\n </Recharts.BarStack>\n );\n};\n\nexport const TypedBar = <TData extends ChartDataValue = ChartDataValue>() =>\n Bar as ComponentType<BarPropsByDataKeyProp<TData>>;\n\nexport default Bar;\n"],"mappings":";;;;;;;;;;;;;AA8CA,IAAa,OAAqB,UAAU;CAC1C,MAAM,EAAE,OAAO,iBAAiB,aAAa,GAAG,SAAS;CAEzD,MAAM,SAAS,gBAAgB;CAC/B,MAAM,YAAY,kBAAkB;CACpC,MAAM,EAAE,WAAW,yBAAyB;CAC5C,MAAM,UAAU,iBAAiB,MAAM,OAAO;CAE9C,MAAM,QAAQ,mBAAmB,cAAc,IAC3C,6BAA6B,eAAe,KAC5C;CAEJ,MAAM,eAAe,SAAS,OAAO,IAAI,gBAAgB,CAAC,KAAK;CAC/D,MAAM,SACJ,WAAW,aACP;EAAC;EAAG;EAAc;EAAc;CAAC,IACjC;EAAC;EAAc;EAAc;EAAG;CAAC;CAEvC,MAAM,MACJ,oBAAC,SAAS,KAAV;EACE,MAAM,mBAAmB,KAAK,IAAI,MAAM,eAAe,MAAM;EAC7D,GAAI;EACK;EACT,MAAM;EACN,QAAQ,YAAY,KAAA,IAAY,SAAS;EACzC,GAAI;CACL,CAAA;CAGH,IAAI,YAAY,KAAA,GACd,OAAO;CAMT,OACE,oBAAC,SAAS,UAAV;EAA4B;EAAiB;EAC1C,UAAA;CACgB,CAAA;AAEvB;AAEA,IAAa,iBACX"}
@@ -3,6 +3,7 @@
3
3
  import { useDesignTokens } from "../../../../lib/theming/hooks/useDesignTokens.mjs";
4
4
  import { AreaDot } from "../AreaDot/AreaDot.mjs";
5
5
  import { isCategoricalColor } from "../../../../lib/tokens/isCategoricalColor.mjs";
6
+ import { useChartAnimation } from "../../hooks/useChartAnimation.mjs";
6
7
  import "react";
7
8
  import { jsx } from "react/jsx-runtime";
8
9
  import * as Recharts from "recharts";
@@ -11,6 +12,7 @@ import * as Recharts from "recharts";
11
12
  var Line = (props) => {
12
13
  const { color: colorFromProps = "sea-green", ...rest } = props;
13
14
  const tokens = useDesignTokens();
15
+ const animation = useChartAnimation();
14
16
  const color = isCategoricalColor(colorFromProps) ? `var(--color--categorical--${colorFromProps})` : colorFromProps;
15
17
  return /* @__PURE__ */ jsx(Recharts.Line, {
16
18
  ...rest,
@@ -18,7 +20,8 @@ var Line = (props) => {
18
20
  activeDot: /* @__PURE__ */ jsx(AreaDot, { color }),
19
21
  dot: false,
20
22
  stroke: color,
21
- strokeWidth: tokens.line["border-width"].value
23
+ strokeWidth: tokens.line["border-width"].value,
24
+ ...animation
22
25
  });
23
26
  };
24
27
  var TypedLine = () => Line;
@@ -1 +1 @@
1
- {"version":3,"file":"Line.mjs","names":[],"sources":["../../../../../../../../../src/components/CartesianChart/components/Line/Line.tsx"],"sourcesContent":["import { type ComponentType, type FC } from \"react\";\nimport * as Recharts from \"recharts\";\nimport { AreaDot } from \"../AreaDot\";\nimport type { CategoricalWithCustomColor } from \"@/lib/tokens/CategoricalColors\";\nimport { isCategoricalColor } from \"@/lib/tokens/isCategoricalColor\";\nimport type {\n ChartDataValue,\n DataKey,\n} from \"@/components/CartesianChart/types\";\nimport { useDesignTokens } from \"@/lib/theming\";\n\nexport interface LineProps<\n TData extends ChartDataValue = ChartDataValue,\n> extends Pick<\n Recharts.LineProps,\n \"className\" | \"key\" | \"xAxisId\" | \"yAxisId\" | \"type\" | \"unit\"\n> {\n dataKey?: DataKey<TData>;\n /** The color of the line. @default \"sea-green\" */\n color?: CategoricalWithCustomColor;\n}\n\n/** @flr-generate all */\nexport const Line: FC<LineProps> = (props) => {\n const { color: colorFromProps = \"sea-green\", ...rest } = props;\n\n const tokens = useDesignTokens();\n\n const color = isCategoricalColor(colorFromProps)\n ? `var(--color--categorical--${colorFromProps})`\n : colorFromProps;\n\n return (\n <Recharts.Line\n {...rest}\n fill={color}\n activeDot={<AreaDot color={color} />}\n dot={false}\n stroke={color}\n strokeWidth={tokens.line[\"border-width\"].value}\n />\n );\n};\n\nexport const TypedLine = <T extends ChartDataValue = ChartDataValue>() =>\n Line as ComponentType<LineProps<T>>;\n\nexport default Line;\n"],"mappings":";;;;;;;;;;AAuBA,IAAa,QAAuB,UAAU;CAC5C,MAAM,EAAE,OAAO,iBAAiB,aAAa,GAAG,SAAS;CAEzD,MAAM,SAAS,gBAAgB;CAE/B,MAAM,QAAQ,mBAAmB,cAAc,IAC3C,6BAA6B,eAAe,KAC5C;CAEJ,OACE,oBAAC,SAAS,MAAV;EACE,GAAI;EACJ,MAAM;EACN,WAAW,oBAAC,SAAD,EAAgB,MAAQ,CAAA;EACnC,KAAK;EACL,QAAQ;EACR,aAAa,OAAO,KAAK,eAAe,CAAC;CAC1C,CAAA;AAEL;AAEA,IAAa,kBACX"}
1
+ {"version":3,"file":"Line.mjs","names":[],"sources":["../../../../../../../../../src/components/CartesianChart/components/Line/Line.tsx"],"sourcesContent":["import { type ComponentType, type FC } from \"react\";\nimport * as Recharts from \"recharts\";\nimport { AreaDot } from \"../AreaDot\";\nimport type { CategoricalWithCustomColor } from \"@/lib/tokens/CategoricalColors\";\nimport { isCategoricalColor } from \"@/lib/tokens/isCategoricalColor\";\nimport type {\n ChartDataValue,\n DataKey,\n} from \"@/components/CartesianChart/types\";\nimport { useChartAnimation } from \"@/components/CartesianChart/hooks/useChartAnimation\";\nimport { useDesignTokens } from \"@/lib/theming\";\n\nexport interface LineProps<\n TData extends ChartDataValue = ChartDataValue,\n> extends Pick<\n Recharts.LineProps,\n \"className\" | \"key\" | \"xAxisId\" | \"yAxisId\" | \"type\" | \"unit\"\n> {\n dataKey?: DataKey<TData>;\n /** The color of the line. @default \"sea-green\" */\n color?: CategoricalWithCustomColor;\n}\n\n/** @flr-generate all */\nexport const Line: FC<LineProps> = (props) => {\n const { color: colorFromProps = \"sea-green\", ...rest } = props;\n\n const tokens = useDesignTokens();\n const animation = useChartAnimation();\n\n const color = isCategoricalColor(colorFromProps)\n ? `var(--color--categorical--${colorFromProps})`\n : colorFromProps;\n\n return (\n <Recharts.Line\n {...rest}\n fill={color}\n activeDot={<AreaDot color={color} />}\n dot={false}\n stroke={color}\n strokeWidth={tokens.line[\"border-width\"].value}\n {...animation}\n />\n );\n};\n\nexport const TypedLine = <T extends ChartDataValue = ChartDataValue>() =>\n Line as ComponentType<LineProps<T>>;\n\nexport default Line;\n"],"mappings":";;;;;;;;;;;AAwBA,IAAa,QAAuB,UAAU;CAC5C,MAAM,EAAE,OAAO,iBAAiB,aAAa,GAAG,SAAS;CAEzD,MAAM,SAAS,gBAAgB;CAC/B,MAAM,YAAY,kBAAkB;CAEpC,MAAM,QAAQ,mBAAmB,cAAc,IAC3C,6BAA6B,eAAe,KAC5C;CAEJ,OACE,oBAAC,SAAS,MAAV;EACE,GAAI;EACJ,MAAM;EACN,WAAW,oBAAC,SAAD,EAAgB,MAAQ,CAAA;EACnC,KAAK;EACL,QAAQ;EACR,aAAa,OAAO,KAAK,eAAe,CAAC;EACzC,GAAI;CACL,CAAA;AAEL;AAEA,IAAa,kBACX"}
@@ -0,0 +1,27 @@
1
+ "use client"
2
+ /* */
3
+ import { useDesignTokens } from "../../../lib/theming/hooks/useDesignTokens.mjs";
4
+ import { useReducedMotion } from "framer-motion";
5
+ //#region src/components/CartesianChart/hooks/useChartAnimation.ts
6
+ /**
7
+ * Animation props for the chart's graphical items. Recharts animates on mount
8
+ * by default and does not look at the user's motion preference on its own.
9
+ *
10
+ * Replaces recharts' default `"auto"`, which means "not during SSR" – moot
11
+ * here, since `ResponsiveContainer` renders nothing on the server.
12
+ *
13
+ * @internal
14
+ */
15
+ var useChartAnimation = () => {
16
+ const prefersReducedMotion = useReducedMotion();
17
+ const tokens = useDesignTokens();
18
+ return {
19
+ isAnimationActive: !prefersReducedMotion,
20
+ animationDuration: parseInt(tokens["cartesian-chart"]["transition-duration"].value),
21
+ animationEasing: "ease"
22
+ };
23
+ };
24
+ //#endregion
25
+ export { useChartAnimation };
26
+
27
+ //# sourceMappingURL=useChartAnimation.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useChartAnimation.mjs","names":[],"sources":["../../../../../../../../src/components/CartesianChart/hooks/useChartAnimation.ts"],"sourcesContent":["import { useReducedMotion } from \"framer-motion\";\nimport { useDesignTokens } from \"@/lib/theming\";\n\n/**\n * Animation props for the chart's graphical items. Recharts animates on mount\n * by default and does not look at the user's motion preference on its own.\n *\n * Replaces recharts' default `\"auto\"`, which means \"not during SSR\" – moot\n * here, since `ResponsiveContainer` renders nothing on the server.\n *\n * @internal\n */\nexport const useChartAnimation = () => {\n const prefersReducedMotion = useReducedMotion();\n const tokens = useDesignTokens();\n\n return {\n isAnimationActive: !prefersReducedMotion,\n animationDuration: parseInt(\n tokens[\"cartesian-chart\"][\"transition-duration\"].value,\n ),\n // Recharts' own default, pinned to match the CSS `ease` of the DonutChart\n // and the ProgressBar.\n animationEasing: \"ease\" as const,\n };\n};\n"],"mappings":";;;;;;;;;;;;;;AAYA,IAAa,0BAA0B;CACrC,MAAM,uBAAuB,iBAAiB;CAC9C,MAAM,SAAS,gBAAgB;CAE/B,OAAO;EACL,mBAAmB,CAAC;EACpB,mBAAmB,SACjB,OAAO,kBAAkB,CAAC,sBAAsB,CAAC,KACnD;EAGA,iBAAiB;CACnB;AACF"}
@@ -4,9 +4,10 @@
4
4
  var donutChart = "flow--donut-chart";
5
5
  var border = "flow--donut-chart--border";
6
6
  var background = "flow--donut-chart--background";
7
+ var fill = "flow--donut-chart--fill";
8
+ var segment = "flow--donut-chart--segment";
7
9
  var value = "flow--donut-chart--value";
8
10
  var info = "flow--donut-chart--info";
9
- var fill = "flow--donut-chart--fill";
10
11
  var success = "flow--donut-chart--success";
11
12
  var danger = "flow--donut-chart--danger";
12
13
  var warning = "flow--donut-chart--warning";
@@ -20,10 +21,12 @@ var DonutChart_module_default = {
20
21
  donutChart,
21
22
  border,
22
23
  background,
24
+ fill,
25
+ segment,
26
+ "donut-chart-fill": "flow--donut-chart--donut-chart-fill",
23
27
  value,
24
28
  "size-l": "flow--donut-chart--size-l",
25
29
  info,
26
- fill,
27
30
  success,
28
31
  danger,
29
32
  warning,
@@ -35,6 +38,6 @@ var DonutChart_module_default = {
35
38
  left
36
39
  };
37
40
  //#endregion
38
- export { background, border, bottom, danger, DonutChart_module_default as default, donutChart, donutChartContainer, fill, info, left, legend, right, success, top, value, warning };
41
+ export { background, border, bottom, danger, DonutChart_module_default as default, donutChart, donutChartContainer, fill, info, left, legend, right, segment, success, top, value, warning };
39
42
 
40
43
  //# sourceMappingURL=DonutChart.module.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"DonutChart.module.mjs","names":[],"sources":["../../../../../../../src/components/DonutChart/DonutChart.module.scss"],"sourcesContent":[".donutChart {\n position: relative;\n width: fit-content;\n height: fit-content;\n flex-shrink: 0;\n\n .border {\n stroke: var(--donut-chart--border-color);\n }\n\n .background {\n stroke: var(--donut-chart--background-color);\n }\n\n .value {\n position: absolute;\n inset: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n text-align: center;\n overflow-wrap: anywhere;\n padding: var(--donut-chart--padding--m);\n }\n\n &.size-l {\n .value {\n font-size: var(--font-size-heading--xl);\n padding: var(--donut-chart--padding--l);\n\n // Raw consumer markup inside the value slot — nothing to class.\n // stylelint-disable-next-line selector-max-type -- consumer markup\n small {\n font-size: var(--font-size-heading--l);\n }\n }\n }\n\n /* Variants */\n @mixin status($status) {\n &.#{$status} {\n .fill {\n stroke: var(--donut-chart--#{$status}-fill-background-color);\n }\n }\n }\n\n @include status(info);\n @include status(success);\n @include status(danger);\n @include status(warning);\n}\n\n.donutChartContainer {\n display: flex;\n gap: var(--donut-chart--spacing-y) var(--donut-chart--spacing-x);\n align-items: center;\n\n &.bottom {\n flex-direction: column;\n }\n\n &.top {\n flex-direction: column-reverse;\n }\n\n &.right {\n .legend {\n justify-content: start;\n }\n }\n\n &.left {\n flex-direction: row-reverse;\n\n .legend {\n justify-content: start;\n }\n }\n}\n"],"mappings":""}
1
+ {"version":3,"file":"DonutChart.module.mjs","names":[],"sources":["../../../../../../../src/components/DonutChart/DonutChart.module.scss"],"sourcesContent":[".donutChart {\n position: relative;\n width: fit-content;\n height: fit-content;\n flex-shrink: 0;\n\n .border {\n stroke: var(--donut-chart--border-color);\n }\n\n .background {\n stroke: var(--donut-chart--background-color);\n }\n\n .fill,\n .segment {\n transform: rotate(var(--donut-chart--fill-rotation));\n transform-box: fill-box;\n transform-origin: center;\n animation: donut-chart-fill var(--donut-chart--transition-duration) ease;\n }\n\n .value {\n position: absolute;\n inset: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n text-align: center;\n overflow-wrap: anywhere;\n padding: var(--donut-chart--padding--m);\n }\n\n &.size-l {\n .value {\n font-size: var(--font-size-heading--xl);\n padding: var(--donut-chart--padding--l);\n\n // Raw consumer markup inside the value slot — nothing to class.\n // stylelint-disable-next-line selector-max-type -- consumer markup\n small {\n font-size: var(--font-size-heading--l);\n }\n }\n }\n\n /* Variants */\n @mixin status($status) {\n &.#{$status} {\n .fill {\n stroke: var(--donut-chart--#{$status}-fill-background-color);\n }\n }\n }\n\n @include status(info);\n @include status(success);\n @include status(danger);\n @include status(warning);\n}\n\n.donutChartContainer {\n display: flex;\n gap: var(--donut-chart--spacing-y) var(--donut-chart--spacing-x);\n align-items: center;\n\n &.bottom {\n flex-direction: column;\n }\n\n &.top {\n flex-direction: column-reverse;\n }\n\n &.right {\n .legend {\n justify-content: start;\n }\n }\n\n &.left {\n flex-direction: row-reverse;\n\n .legend {\n justify-content: start;\n }\n }\n}\n\n/* The implicit \"to\" keyframe picks up the fill's own offset and rotation. */\n@keyframes donut-chart-fill {\n from {\n stroke-dashoffset: var(--donut-chart--circumference);\n transform: rotate(-90deg);\n }\n}\n"],"mappings":""}
@@ -5,6 +5,16 @@ import { getCategoricalColorByIndex } from "../../../lib/tokens/getCategoricalCo
5
5
  import DonutChart_module_default from "../DonutChart.module.mjs";
6
6
  import { jsx } from "react/jsx-runtime";
7
7
  //#region src/components/DonutChart/components/DonutChartFill.tsx
8
+ /**
9
+ * The rotation is a custom property instead of a `transform` attribute so that
10
+ * the load-in keyframes can animate it – growing every segment out of 12
11
+ * o'clock instead of leaving gaps between them. They need the circumference,
12
+ * too, to animate out of an empty circle.
13
+ */
14
+ var fillStyle = (rotation, circumference) => ({
15
+ "--donut-chart--fill-rotation": `${rotation}deg`,
16
+ "--donut-chart--circumference": circumference
17
+ });
8
18
  var DonutChartFill = (props) => {
9
19
  const { center, value = 0, radius, segments, maxValue } = props;
10
20
  const circumference = 2 * radius * Math.PI;
@@ -16,7 +26,7 @@ var DonutChartFill = (props) => {
16
26
  r: radius,
17
27
  strokeDasharray: `${circumference} ${circumference}`,
18
28
  strokeDashoffset: circumference - percent / 100 * circumference,
19
- transform: `rotate(-90 ${center} ${center})`
29
+ style: fillStyle(-90, circumference)
20
30
  });
21
31
  let rotationOffset = 0;
22
32
  return segments.map((s, i) => {
@@ -25,13 +35,14 @@ var DonutChartFill = (props) => {
25
35
  rotationOffset = rotationOffset + 360 / 100 * segmentPercent;
26
36
  const color = !s.color || isCategoricalColor(s.color) ? `var(--color--categorical--${s.color ?? getCategoricalColorByIndex(i)})` : s.color;
27
37
  return /* @__PURE__ */ jsx("circle", {
38
+ className: DonutChart_module_default.segment,
28
39
  cx: center,
29
40
  cy: center,
30
41
  r: radius,
31
42
  strokeDasharray: `${circumference} ${circumference}`,
32
43
  strokeDashoffset: circumference - segmentPercent / 100 * circumference,
33
44
  stroke: color,
34
- transform: `rotate(${-90 + currentRotationOffset} ${center} ${center})`
45
+ style: fillStyle(-90 + currentRotationOffset, circumference)
35
46
  }, i);
36
47
  });
37
48
  };
@@ -1 +1 @@
1
- {"version":3,"file":"DonutChartFill.mjs","names":[],"sources":["../../../../../../../../src/components/DonutChart/components/DonutChartFill.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport styles from \"@/components/DonutChart/DonutChart.module.scss\";\nimport type { DonutChartProps } from \"@/components/DonutChart\";\nimport { getCategoricalColorByIndex } from \"@/lib/tokens/getCategoricalColorByIndex\";\nimport { isCategoricalColor } from \"@/lib/tokens/isCategoricalColor\";\n\ninterface Props extends Pick<DonutChartProps, \"segments\"> {\n center: number;\n value?: number;\n radius: number;\n maxValue: number;\n}\n\nexport const DonutChartFill: FC<Props> = (props) => {\n const { center, value = 0, radius, segments, maxValue } = props;\n\n const circumference = 2 * radius * Math.PI;\n\n const percent = (100 / maxValue) * value;\n\n if (!segments) {\n return (\n <circle\n className={styles.fill}\n cx={center}\n cy={center}\n r={radius}\n strokeDasharray={`${circumference} ${circumference}`}\n strokeDashoffset={circumference - (percent / 100) * circumference}\n transform={`rotate(-90 ${center} ${center})`}\n />\n );\n }\n\n let rotationOffset = 0;\n\n return segments.map((s, i) => {\n const segmentPercent = (100 / maxValue) * s.value;\n\n const currentRotationOffset = rotationOffset;\n\n rotationOffset = rotationOffset + (360 / 100) * segmentPercent;\n\n const color =\n !s.color || isCategoricalColor(s.color)\n ? `var(--color--categorical--${s.color ?? getCategoricalColorByIndex(i)})`\n : s.color;\n\n return (\n <circle\n key={i}\n cx={center}\n cy={center}\n r={radius}\n strokeDasharray={`${circumference} ${circumference}`}\n strokeDashoffset={\n circumference - (segmentPercent / 100) * circumference\n }\n stroke={color}\n transform={`rotate(${-90 + currentRotationOffset} ${center} ${center})`}\n />\n );\n });\n};\n"],"mappings":";;;;;;;AAaA,IAAa,kBAA6B,UAAU;CAClD,MAAM,EAAE,QAAQ,QAAQ,GAAG,QAAQ,UAAU,aAAa;CAE1D,MAAM,gBAAgB,IAAI,SAAS,KAAK;CAExC,MAAM,UAAW,MAAM,WAAY;CAEnC,IAAI,CAAC,UACH,OACE,oBAAC,UAAD;EACE,WAAW,0BAAO;EAClB,IAAI;EACJ,IAAI;EACJ,GAAG;EACH,iBAAiB,GAAG,cAAc,GAAG;EACrC,kBAAkB,gBAAiB,UAAU,MAAO;EACpD,WAAW,cAAc,OAAO,GAAG,OAAO;CAC3C,CAAA;CAIL,IAAI,iBAAiB;CAErB,OAAO,SAAS,KAAK,GAAG,MAAM;EAC5B,MAAM,iBAAkB,MAAM,WAAY,EAAE;EAE5C,MAAM,wBAAwB;EAE9B,iBAAiB,iBAAkB,MAAM,MAAO;EAEhD,MAAM,QACJ,CAAC,EAAE,SAAS,mBAAmB,EAAE,KAAK,IAClC,6BAA6B,EAAE,SAAS,2BAA2B,CAAC,EAAE,KACtE,EAAE;EAER,OACE,oBAAC,UAAD;GAEE,IAAI;GACJ,IAAI;GACJ,GAAG;GACH,iBAAiB,GAAG,cAAc,GAAG;GACrC,kBACE,gBAAiB,iBAAiB,MAAO;GAE3C,QAAQ;GACR,WAAW,UAAU,MAAM,sBAAsB,GAAG,OAAO,GAAG,OAAO;EACtE,GAVM,CAUN;CAEL,CAAC;AACH"}
1
+ {"version":3,"file":"DonutChartFill.mjs","names":[],"sources":["../../../../../../../../src/components/DonutChart/components/DonutChartFill.tsx"],"sourcesContent":["import type { CSSProperties, FC } from \"react\";\nimport styles from \"@/components/DonutChart/DonutChart.module.scss\";\nimport type { DonutChartProps } from \"@/components/DonutChart\";\nimport { getCategoricalColorByIndex } from \"@/lib/tokens/getCategoricalColorByIndex\";\nimport { isCategoricalColor } from \"@/lib/tokens/isCategoricalColor\";\n\ninterface Props extends Pick<DonutChartProps, \"segments\"> {\n center: number;\n value?: number;\n radius: number;\n maxValue: number;\n}\n\n/**\n * The rotation is a custom property instead of a `transform` attribute so that\n * the load-in keyframes can animate it – growing every segment out of 12\n * o'clock instead of leaving gaps between them. They need the circumference,\n * too, to animate out of an empty circle.\n */\nconst fillStyle = (rotation: number, circumference: number) =>\n ({\n \"--donut-chart--fill-rotation\": `${rotation}deg`,\n \"--donut-chart--circumference\": circumference,\n }) as CSSProperties;\n\nexport const DonutChartFill: FC<Props> = (props) => {\n const { center, value = 0, radius, segments, maxValue } = props;\n\n const circumference = 2 * radius * Math.PI;\n\n const percent = (100 / maxValue) * value;\n\n if (!segments) {\n return (\n <circle\n className={styles.fill}\n cx={center}\n cy={center}\n r={radius}\n strokeDasharray={`${circumference} ${circumference}`}\n strokeDashoffset={circumference - (percent / 100) * circumference}\n style={fillStyle(-90, circumference)}\n />\n );\n }\n\n let rotationOffset = 0;\n\n return segments.map((s, i) => {\n const segmentPercent = (100 / maxValue) * s.value;\n\n const currentRotationOffset = rotationOffset;\n\n rotationOffset = rotationOffset + (360 / 100) * segmentPercent;\n\n const color =\n !s.color || isCategoricalColor(s.color)\n ? `var(--color--categorical--${s.color ?? getCategoricalColorByIndex(i)})`\n : s.color;\n\n // Index keys: a segment added after mount animates alone out of 12 o'clock,\n // over the segments already there.\n return (\n <circle\n key={i}\n className={styles.segment}\n cx={center}\n cy={center}\n r={radius}\n strokeDasharray={`${circumference} ${circumference}`}\n strokeDashoffset={\n circumference - (segmentPercent / 100) * circumference\n }\n stroke={color}\n style={fillStyle(-90 + currentRotationOffset, circumference)}\n />\n );\n });\n};\n"],"mappings":";;;;;;;;;;;;;AAmBA,IAAM,aAAa,UAAkB,mBAClC;CACC,gCAAgC,GAAG,SAAS;CAC5C,gCAAgC;AAClC;AAEF,IAAa,kBAA6B,UAAU;CAClD,MAAM,EAAE,QAAQ,QAAQ,GAAG,QAAQ,UAAU,aAAa;CAE1D,MAAM,gBAAgB,IAAI,SAAS,KAAK;CAExC,MAAM,UAAW,MAAM,WAAY;CAEnC,IAAI,CAAC,UACH,OACE,oBAAC,UAAD;EACE,WAAW,0BAAO;EAClB,IAAI;EACJ,IAAI;EACJ,GAAG;EACH,iBAAiB,GAAG,cAAc,GAAG;EACrC,kBAAkB,gBAAiB,UAAU,MAAO;EACpD,OAAO,UAAU,KAAK,aAAa;CACpC,CAAA;CAIL,IAAI,iBAAiB;CAErB,OAAO,SAAS,KAAK,GAAG,MAAM;EAC5B,MAAM,iBAAkB,MAAM,WAAY,EAAE;EAE5C,MAAM,wBAAwB;EAE9B,iBAAiB,iBAAkB,MAAM,MAAO;EAEhD,MAAM,QACJ,CAAC,EAAE,SAAS,mBAAmB,EAAE,KAAK,IAClC,6BAA6B,EAAE,SAAS,2BAA2B,CAAC,EAAE,KACtE,EAAE;EAIR,OACE,oBAAC,UAAD;GAEE,WAAW,0BAAO;GAClB,IAAI;GACJ,IAAI;GACJ,GAAG;GACH,iBAAiB,GAAG,cAAc,GAAG;GACrC,kBACE,gBAAiB,iBAAiB,MAAO;GAE3C,QAAQ;GACR,OAAO,UAAU,MAAM,uBAAuB,aAAa;EAC5D,GAXM,CAWN;CAEL,CAAC;AACH"}
@@ -1 +1 @@
1
- {"version":3,"file":"Popover.module.mjs","names":[],"sources":["../../../../../../../src/components/Popover/Popover.module.scss"],"sourcesContent":["@use \"@/styles/mixins/scrollbar\";\n\n/* Variants */\n\n/*\n * A non-modal popover stays in the document and scrolls with the page, so the\n * height react-aria caps it at — the room left in the viewport when it was last\n * measured — is not a limit that applies to it. Anchored below the fold that\n * room is zero, and the hint renders as a two-pixel sliver.\n *\n * `useOverlayPosition` writes the value straight onto the element\n * (`overlay.style.maxHeight = …`) rather than returning it among its props, so\n * no React style can remove it and only `!important` reaches it.\n */\n.non-modal {\n max-height: none !important;\n}\n\n.popover {\n background-color: var(--popover--background-color);\n box-shadow: var(--popover--box-shadow);\n border-radius: var(--popover--corner-radius);\n display: flex;\n flex-direction: column;\n\n --size-px--s--negative: calc(var(--size-px--s) * -1);\n\n min-width: var(--popover--min-width);\n border-width: var(--popover--border-width);\n border-style: var(--popover--border-style);\n border-color: var(--popover--border-color);\n max-width: calc(100% - 2 * var(--popover--viewport-padding));\n\n :where(.content) {\n @include scrollbar.scrollbar;\n\n overflow-y: auto;\n\n &:focus-visible {\n outline: none;\n }\n }\n\n .tip {\n width: var(--popover--tip-width);\n\n .tipIcon {\n display: block;\n fill: var(--popover--background-color);\n stroke: var(--popover--border-color);\n stroke-width: var(--popover--border-width);\n }\n }\n\n &[data-placement=\"top\"] {\n --origin: translateY(var(--size-px--s));\n\n &:has(.tip) {\n margin-bottom: var(--popover--tip-height);\n }\n }\n\n &[data-placement=\"bottom\"] {\n --origin: translateY(var(--size-px--s--negative));\n\n &:has(.tip) {\n margin-top: var(--popover--tip-height);\n }\n\n .tip .tipIcon {\n transform: rotate(180deg);\n }\n }\n\n &[data-placement=\"right\"] {\n --origin: translateX(var(--size-px--s--negative));\n\n &:has(.tip) {\n margin-inline-start: var(--popover--tip-height);\n }\n\n .tip .tipIcon {\n transform: rotate(90deg);\n }\n }\n\n &[data-placement=\"left\"] {\n --origin: translateX(var(--size-px--s));\n\n &:has(.tip) {\n margin-inline-end: var(--popover--tip-height);\n }\n\n .tip .tipIcon {\n transform: rotate(-90deg);\n }\n }\n\n &[data-entering] {\n animation: popover-slide var(--transition--duration--default);\n }\n\n &[data-exiting] {\n animation: popover-slide var(--transition--duration--default) reverse\n ease-in;\n pointer-events: none;\n }\n\n &:has(:global(.flow--options):empty) {\n display: none;\n }\n}\n\n@keyframes popover-slide {\n from {\n transform: var(--origin);\n opacity: 0;\n }\n\n to {\n transform: translateY(0);\n opacity: 1;\n }\n}\n"],"mappings":""}
1
+ {"version":3,"file":"Popover.module.mjs","names":[],"sources":["../../../../../../../src/components/Popover/Popover.module.scss"],"sourcesContent":["@use \"@/styles/mixins/scrollbar\";\n\n/* Variants */\n\n/*\n * A non-modal popover stays in the document and scrolls with the page, so the\n * height react-aria caps it at — the room left in the viewport when it was last\n * measured — is not a limit that applies to it. Anchored below the fold that\n * room is zero, and the hint renders as a two-pixel sliver.\n *\n * `useOverlayPosition` writes the value straight onto the element\n * (`overlay.style.maxHeight = …`) rather than returning it among its props, so\n * no React style can remove it and only `!important` reaches it.\n */\n.non-modal {\n max-height: none !important;\n\n /*\n * The lowest level that still puts the popover in front of the page. Claiming\n * none at all left it in the `z-index: auto` group, where paint order is tree\n * order — so anything positioned that came later in the document painted over\n * it, and a `position: relative` written as a containing block for something\n * inside it was enough (a `TabNavigation` in a `LayoutCard` below the anchor,\n * #3232). Nothing an overlay can read tells that apart from a deliberate\n * claim, so it has to outrank the whole group.\n *\n * The cost is app chrome that claims level 1 itself: the popover comes later\n * in the document than a header does, so it now wins that tie. Chrome that has\n * to stay above a coach mark claims 2 — the docs site's own header does.\n */\n z-index: 1;\n}\n\n.popover {\n background-color: var(--popover--background-color);\n box-shadow: var(--popover--box-shadow);\n border-radius: var(--popover--corner-radius);\n display: flex;\n flex-direction: column;\n\n --size-px--s--negative: calc(var(--size-px--s) * -1);\n\n min-width: var(--popover--min-width);\n border-width: var(--popover--border-width);\n border-style: var(--popover--border-style);\n border-color: var(--popover--border-color);\n max-width: calc(100% - 2 * var(--popover--viewport-padding));\n\n :where(.content) {\n @include scrollbar.scrollbar;\n\n overflow-y: auto;\n\n &:focus-visible {\n outline: none;\n }\n }\n\n .tip {\n width: var(--popover--tip-width);\n\n .tipIcon {\n display: block;\n fill: var(--popover--background-color);\n stroke: var(--popover--border-color);\n stroke-width: var(--popover--border-width);\n }\n }\n\n &[data-placement=\"top\"] {\n --origin: translateY(var(--size-px--s));\n\n &:has(.tip) {\n margin-bottom: var(--popover--tip-height);\n }\n }\n\n &[data-placement=\"bottom\"] {\n --origin: translateY(var(--size-px--s--negative));\n\n &:has(.tip) {\n margin-top: var(--popover--tip-height);\n }\n\n .tip .tipIcon {\n transform: rotate(180deg);\n }\n }\n\n &[data-placement=\"right\"] {\n --origin: translateX(var(--size-px--s--negative));\n\n &:has(.tip) {\n margin-inline-start: var(--popover--tip-height);\n }\n\n .tip .tipIcon {\n transform: rotate(90deg);\n }\n }\n\n &[data-placement=\"left\"] {\n --origin: translateX(var(--size-px--s));\n\n &:has(.tip) {\n margin-inline-end: var(--popover--tip-height);\n }\n\n .tip .tipIcon {\n transform: rotate(-90deg);\n }\n }\n\n &[data-entering] {\n animation: popover-slide var(--transition--duration--default);\n }\n\n &[data-exiting] {\n animation: popover-slide var(--transition--duration--default) reverse\n ease-in;\n pointer-events: none;\n }\n\n &:has(:global(.flow--options):empty) {\n display: none;\n }\n}\n\n@keyframes popover-slide {\n from {\n transform: var(--origin);\n opacity: 0;\n }\n\n to {\n transform: translateY(0);\n opacity: 1;\n }\n}\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"NonModalPopoverContent.mjs","names":[],"sources":["../../../../../../../../../src/components/Popover/components/NonModalPopoverContent/NonModalPopoverContent.tsx"],"sourcesContent":["import type { FC, PropsWithChildren, Ref, RefObject } from \"react\";\nimport { useEffect, useId, useRef } from \"react\";\nimport clsx from \"clsx\";\nimport { useObjectRef, useOverlayPosition } from \"react-aria\";\nimport type { Placement } from \"react-aria\";\nimport { useEnterAnimation, useExitAnimation } from \"@react-aria/utils\";\nimport styles from \"../../Popover.module.scss\";\nimport type { PropsWithClassName } from \"@/lib/types/props\";\nimport { popoverViewportPadding } from \"../../viewportPadding\";\nimport { popoverWidthStyle } from \"../../widthStyle\";\n\nexport interface NonModalPopoverContentProps\n extends PropsWithChildren, PropsWithClassName {\n withTip?: boolean;\n isOpen?: boolean;\n width?: string | number;\n placement?: Placement;\n offset?: number;\n crossOffset?: number;\n /** Swallowed on purpose — the stylesheet overrides `max-height` here. */\n maxHeight?: number;\n shouldFlip?: boolean;\n shouldUpdatePosition?: boolean;\n arrowBoundaryOffset?: number;\n boundaryElement?: Element;\n /** The id react-aria's trigger points its `aria-controls` at. */\n id?: string;\n onOpenChange: (isOpen: boolean) => void;\n ref?: Ref<HTMLElement>;\n triggerRef: RefObject<Element | null>;\n}\n\ninterface NonModalPopoverContentInnerProps extends Omit<\n NonModalPopoverContentProps,\n \"ref\"\n> {\n overlayRef: RefObject<HTMLDivElement | null>;\n isExiting: boolean;\n}\n\n/*\n * `useOverlayPosition` recalculates when the window resizes, when a scroll\n * container scrolls, and when the anchor or the popover changes *size*. It never\n * notices the anchor merely *moving*, because a popover normally opens on a user\n * interaction, long after the page settled.\n *\n * This one opens itself, so it places itself into a page that is still filling\n * in — and anything appearing above the anchor then pushes the anchor out from\n * under it. Remotely that is the normal case, not an edge case: the host\n * materializes the page in pieces as they arrive over the connection.\n *\n * Observing the ancestors covers it. In block layout an element moves because\n * something around it changed size, and a resized ancestor is the one signal\n * every such reflow has in common. What it does not catch is an ancestor of\n * fixed height rearranging inside — rare, and the next scroll or resize\n * corrects it.\n */\nconst useRepositionWhenAnchorMoves = (\n anchorRef: RefObject<Element | null>,\n isOpen: boolean,\n updatePosition: () => void,\n): void => {\n useEffect(() => {\n // Read inside the effect. A coach mark that is open from its first render\n // renders before the anchor's ref is attached, and a ref filling in does not\n // re-render anything — so reading during render would see `null`, bail, and\n // leave nothing observing.\n const anchor = anchorRef.current;\n\n if (!isOpen || !anchor) {\n return;\n }\n\n const observer = new ResizeObserver(updatePosition);\n\n for (\n let element = anchor.parentElement;\n element;\n element = element.parentElement\n ) {\n observer.observe(element);\n }\n\n return () => observer.disconnect();\n }, [anchorRef, isOpen, updatePosition]);\n};\n\n/*\n * The non-modal popover deliberately skips react-aria's `usePopover`, which is\n * what a popover normally builds on. That hook couples three things Flow does\n * not want here: it locks page scrolling, it hides the rest of the page from\n * assistive tech, and — the reason this component exists — it closes the\n * popover on the first scroll, with no way to opt out.\n *\n * What is left is `useOverlayPosition` for the anchoring, public react-aria API.\n * The popover therefore tracks its trigger while the page scrolls, and its\n * content stays plain content: no role, no label, no focus of its own.\n *\n * It is not portalled either. A popover that is announced by nothing has to be\n * findable where it belongs, and a portal to the end of `<body>` puts it behind\n * the whole page in reading order — so it renders where it was written, right\n * next to what it points at. Being absolutely positioned it still takes no\n * space; what it does inherit is its surroundings, so an ancestor that clips\n * (`overflow: hidden`) or a stacking context can cut it off.\n *\n * Mounting is split across two components for the same reason `Aria.Popover`\n * splits it: the closing animation has to outlive `isOpen`, so the element that\n * plays it cannot be unmounted by the render that closes it. This outer half\n * keeps the ref and the mount decision and survives across open and closed; the\n * inner half holds the positioning and remounts on every open, which is what\n * resets the entry animation.\n */\nexport const NonModalPopoverContent: FC<NonModalPopoverContentProps> = (\n props,\n) => {\n const { isOpen = false, ref, ...rest } = props;\n\n const overlayRef = useObjectRef(ref as Ref<HTMLDivElement>);\n\n const isExiting = useExitAnimation(overlayRef, isOpen);\n\n if (!isOpen && !isExiting) {\n return null;\n }\n\n return (\n <NonModalPopoverContentInner\n {...rest}\n overlayRef={overlayRef}\n isOpen={isOpen}\n isExiting={isExiting}\n />\n );\n};\n\nconst NonModalPopoverContentInner: FC<NonModalPopoverContentInnerProps> = (\n props,\n) => {\n const {\n children,\n className,\n withTip,\n isOpen = false,\n isExiting,\n width,\n id,\n onOpenChange,\n overlayRef,\n triggerRef,\n // Named one by one so that everything left over is a DOM prop and reaches\n // the element. Funnelling the rest into the positioning instead drops\n // `aria-*`, `data-*` and the like, which `Aria.Popover` forwards on the\n // modal path.\n placement: requestedPlacement,\n offset,\n crossOffset,\n maxHeight: ignoredMaxHeight,\n shouldFlip,\n shouldUpdatePosition,\n arrowBoundaryOffset,\n boundaryElement,\n ...rest\n } = props;\n\n void ignoredMaxHeight;\n\n const positionProps = {\n placement: requestedPlacement,\n offset,\n crossOffset,\n shouldFlip,\n shouldUpdatePosition,\n arrowBoundaryOffset,\n boundaryElement,\n };\n\n const arrowRef = useRef<HTMLDivElement>(null);\n const detailsId = useId();\n\n const { overlayProps, arrowProps, placement, updatePosition } =\n useOverlayPosition({\n ...positionProps,\n targetRef: triggerRef,\n overlayRef,\n arrowRef,\n isOpen,\n offset: positionProps.offset ?? 8,\n containerPadding: popoverViewportPadding,\n });\n\n useRepositionWhenAnchorMoves(triggerRef, isOpen, updatePosition);\n\n /*\n * Until it has a placement, `useOverlayPosition` parks the popover in the top\n * left corner (`position: fixed; top: 0; left: 0`) — it has not measured the\n * anchor yet. Rendered on a server that corner is what ships, and the popover\n * sits there until hydration measures; an anchor given by id is resolved a\n * frame later still. Either way it is visibly in the wrong place first and\n * jumps to the anchor after, so keep it out of sight until it knows where it\n * belongs. It stays in the DOM, which is what its place in the reading order\n * and `aria-details` depend on.\n */\n const isPositioned = placement !== null;\n\n // Held back until the popover knows where it belongs — an entry animation\n // that plays while the popover is still hidden is one the user never sees.\n const isEntering = useEnterAnimation(overlayRef, isPositioned);\n\n /*\n * Nothing announces this popover, so the trigger points at it: `aria-details`\n * tells assistive tech that there is related content and offers a way over to\n * it — unlike `aria-describedby`, which would flatten the popover into a\n * string and put its buttons out of reach.\n *\n * Set on the trigger element itself, because that element belongs to whoever\n * rendered it. Whatever it carried before is restored on the way out.\n */\n useEffect(() => {\n const trigger = triggerRef.current;\n\n if (!isOpen || !trigger) {\n return;\n }\n\n const previous = trigger.getAttribute(\"aria-details\");\n trigger.setAttribute(\n \"aria-details\",\n previous ? `${previous} ${detailsId}` : detailsId,\n );\n\n return () => {\n if (previous === null) {\n trigger.removeAttribute(\"aria-details\");\n } else {\n trigger.setAttribute(\"aria-details\", previous);\n }\n };\n }, [isOpen, triggerRef, detailsId]);\n\n // Escape closes it. react-aria would do this through `useOverlay`, which is\n // part of the machinery this component leaves out.\n useEffect(() => {\n if (!isOpen) {\n return;\n }\n\n const closeOnEscape = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n onOpenChange(false);\n }\n };\n\n document.addEventListener(\"keydown\", closeOnEscape);\n return () => document.removeEventListener(\"keydown\", closeOnEscape);\n }, [isOpen, onOpenChange]);\n\n return (\n <div\n {...rest}\n {...overlayProps}\n id={id}\n ref={overlayRef}\n className={clsx(className, styles[\"non-modal\"])}\n data-placement={placement ?? undefined}\n data-entering={isEntering || undefined}\n data-exiting={isExiting || undefined}\n style={{\n ...overlayProps.style,\n /*\n * Two things `useOverlayPosition` adds for an overlay portalled to the\n * end of `<body>` and pinned to the viewport. This one renders where it\n * stands and scrolls with the page, so both are wrong here.\n *\n * `z-index: 100000` would put it in front of the whole application — it\n * scrolled over the docs site's sticky header. Claiming no stacking\n * level leaves that to the page: it still covers the ordinary content\n * around it, and app chrome that sets a `z-index` keeps its place above.\n *\n * The `max-height` it caps the overlay at is wrong here for the same\n * reason, but it is written straight onto the element and has to be\n * undone in CSS — see `.non-modal` in Popover.module.scss.\n */\n zIndex: undefined,\n ...popoverWidthStyle(width),\n ...(isPositioned ? {} : { visibility: \"hidden\" }),\n }}\n >\n {withTip && (\n <div\n {...arrowProps}\n ref={arrowRef}\n className={styles.tip}\n data-placement={placement ?? undefined}\n style={{\n // What <Aria.OverlayArrow /> contributes on top of `arrowProps`:\n // it lifts the tip out of the flow and centres it on the anchor.\n position: \"absolute\",\n transform:\n placement === \"top\" || placement === \"bottom\"\n ? \"translateX(-50%)\"\n : \"translateY(-50%)\",\n // `arrowProps.style` carries the offset along the popover's edge and\n // leaves the other axis `undefined` — which still overwrites. So the\n // edge the tip sits on is set last: spread first, it silently lost\n // `top: 100%` and the tip jumped to the popover's top edge, pointing\n // away from an anchor that was below it.\n ...arrowProps.style,\n ...(placement ? { [placement]: \"100%\" } : {}),\n }}\n >\n <svg\n className={styles.tipIcon}\n width={16}\n height={16}\n viewBox=\"0 0 16 16\"\n >\n <path d=\"M0 0 L8 8 L16 0\" />\n </svg>\n </div>\n )}\n <div className={styles.content} id={detailsId}>\n {children}\n </div>\n </div>\n );\n};\n\nexport default NonModalPopoverContent;\n"],"mappings":"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"}
1
+ {"version":3,"file":"NonModalPopoverContent.mjs","names":[],"sources":["../../../../../../../../../src/components/Popover/components/NonModalPopoverContent/NonModalPopoverContent.tsx"],"sourcesContent":["import type { FC, PropsWithChildren, Ref, RefObject } from \"react\";\nimport { useEffect, useId, useRef } from \"react\";\nimport clsx from \"clsx\";\nimport { useObjectRef, useOverlayPosition } from \"react-aria\";\nimport type { Placement } from \"react-aria\";\nimport { useEnterAnimation, useExitAnimation } from \"@react-aria/utils\";\nimport styles from \"../../Popover.module.scss\";\nimport type { PropsWithClassName } from \"@/lib/types/props\";\nimport { popoverViewportPadding } from \"../../viewportPadding\";\nimport { popoverWidthStyle } from \"../../widthStyle\";\n\nexport interface NonModalPopoverContentProps\n extends PropsWithChildren, PropsWithClassName {\n withTip?: boolean;\n isOpen?: boolean;\n width?: string | number;\n placement?: Placement;\n offset?: number;\n crossOffset?: number;\n /** Swallowed on purpose — the stylesheet overrides `max-height` here. */\n maxHeight?: number;\n shouldFlip?: boolean;\n shouldUpdatePosition?: boolean;\n arrowBoundaryOffset?: number;\n boundaryElement?: Element;\n /** The id react-aria's trigger points its `aria-controls` at. */\n id?: string;\n onOpenChange: (isOpen: boolean) => void;\n ref?: Ref<HTMLElement>;\n triggerRef: RefObject<Element | null>;\n}\n\ninterface NonModalPopoverContentInnerProps extends Omit<\n NonModalPopoverContentProps,\n \"ref\"\n> {\n overlayRef: RefObject<HTMLDivElement | null>;\n isExiting: boolean;\n}\n\n/*\n * `useOverlayPosition` recalculates when the window resizes, when a scroll\n * container scrolls, and when the anchor or the popover changes *size*. It never\n * notices the anchor merely *moving*, because a popover normally opens on a user\n * interaction, long after the page settled.\n *\n * This one opens itself, so it places itself into a page that is still filling\n * in — and anything appearing above the anchor then pushes the anchor out from\n * under it. Remotely that is the normal case, not an edge case: the host\n * materializes the page in pieces as they arrive over the connection.\n *\n * Observing the ancestors covers it. In block layout an element moves because\n * something around it changed size, and a resized ancestor is the one signal\n * every such reflow has in common. What it does not catch is an ancestor of\n * fixed height rearranging inside — rare, and the next scroll or resize\n * corrects it.\n */\nconst useRepositionWhenAnchorMoves = (\n anchorRef: RefObject<Element | null>,\n isOpen: boolean,\n updatePosition: () => void,\n): void => {\n useEffect(() => {\n // Read inside the effect. A coach mark that is open from its first render\n // renders before the anchor's ref is attached, and a ref filling in does not\n // re-render anything — so reading during render would see `null`, bail, and\n // leave nothing observing.\n const anchor = anchorRef.current;\n\n if (!isOpen || !anchor) {\n return;\n }\n\n const observer = new ResizeObserver(updatePosition);\n\n for (\n let element = anchor.parentElement;\n element;\n element = element.parentElement\n ) {\n observer.observe(element);\n }\n\n return () => observer.disconnect();\n }, [anchorRef, isOpen, updatePosition]);\n};\n\n/*\n * The non-modal popover deliberately skips react-aria's `usePopover`, which is\n * what a popover normally builds on. That hook couples three things Flow does\n * not want here: it locks page scrolling, it hides the rest of the page from\n * assistive tech, and — the reason this component exists — it closes the\n * popover on the first scroll, with no way to opt out.\n *\n * What is left is `useOverlayPosition` for the anchoring, public react-aria API.\n * The popover therefore tracks its trigger while the page scrolls, and its\n * content stays plain content: no role, no label, no focus of its own.\n *\n * It is not portalled either. A popover that is announced by nothing has to be\n * findable where it belongs, and a portal to the end of `<body>` puts it behind\n * the whole page in reading order — so it renders where it was written, right\n * next to what it points at. Being absolutely positioned it still takes no\n * space; what it does inherit is its surroundings, so an ancestor that clips\n * (`overflow: hidden`) or a stacking context can cut it off.\n *\n * Mounting is split across two components for the same reason `Aria.Popover`\n * splits it: the closing animation has to outlive `isOpen`, so the element that\n * plays it cannot be unmounted by the render that closes it. This outer half\n * keeps the ref and the mount decision and survives across open and closed; the\n * inner half holds the positioning and remounts on every open, which is what\n * resets the entry animation.\n */\nexport const NonModalPopoverContent: FC<NonModalPopoverContentProps> = (\n props,\n) => {\n const { isOpen = false, ref, ...rest } = props;\n\n const overlayRef = useObjectRef(ref as Ref<HTMLDivElement>);\n\n const isExiting = useExitAnimation(overlayRef, isOpen);\n\n if (!isOpen && !isExiting) {\n return null;\n }\n\n return (\n <NonModalPopoverContentInner\n {...rest}\n overlayRef={overlayRef}\n isOpen={isOpen}\n isExiting={isExiting}\n />\n );\n};\n\nconst NonModalPopoverContentInner: FC<NonModalPopoverContentInnerProps> = (\n props,\n) => {\n const {\n children,\n className,\n withTip,\n isOpen = false,\n isExiting,\n width,\n id,\n onOpenChange,\n overlayRef,\n triggerRef,\n // Named one by one so that everything left over is a DOM prop and reaches\n // the element. Funnelling the rest into the positioning instead drops\n // `aria-*`, `data-*` and the like, which `Aria.Popover` forwards on the\n // modal path.\n placement: requestedPlacement,\n offset,\n crossOffset,\n maxHeight: ignoredMaxHeight,\n shouldFlip,\n shouldUpdatePosition,\n arrowBoundaryOffset,\n boundaryElement,\n ...rest\n } = props;\n\n void ignoredMaxHeight;\n\n const positionProps = {\n placement: requestedPlacement,\n offset,\n crossOffset,\n shouldFlip,\n shouldUpdatePosition,\n arrowBoundaryOffset,\n boundaryElement,\n };\n\n const arrowRef = useRef<HTMLDivElement>(null);\n const detailsId = useId();\n\n const { overlayProps, arrowProps, placement, updatePosition } =\n useOverlayPosition({\n ...positionProps,\n targetRef: triggerRef,\n overlayRef,\n arrowRef,\n isOpen,\n offset: positionProps.offset ?? 8,\n containerPadding: popoverViewportPadding,\n });\n\n useRepositionWhenAnchorMoves(triggerRef, isOpen, updatePosition);\n\n /*\n * Until it has a placement, `useOverlayPosition` parks the popover in the top\n * left corner (`position: fixed; top: 0; left: 0`) — it has not measured the\n * anchor yet. Rendered on a server that corner is what ships, and the popover\n * sits there until hydration measures; an anchor given by id is resolved a\n * frame later still. Either way it is visibly in the wrong place first and\n * jumps to the anchor after, so keep it out of sight until it knows where it\n * belongs. It stays in the DOM, which is what its place in the reading order\n * and `aria-details` depend on.\n */\n const isPositioned = placement !== null;\n\n // Held back until the popover knows where it belongs — an entry animation\n // that plays while the popover is still hidden is one the user never sees.\n const isEntering = useEnterAnimation(overlayRef, isPositioned);\n\n /*\n * Nothing announces this popover, so the trigger points at it: `aria-details`\n * tells assistive tech that there is related content and offers a way over to\n * it — unlike `aria-describedby`, which would flatten the popover into a\n * string and put its buttons out of reach.\n *\n * Set on the trigger element itself, because that element belongs to whoever\n * rendered it. Whatever it carried before is restored on the way out.\n */\n useEffect(() => {\n const trigger = triggerRef.current;\n\n if (!isOpen || !trigger) {\n return;\n }\n\n const previous = trigger.getAttribute(\"aria-details\");\n trigger.setAttribute(\n \"aria-details\",\n previous ? `${previous} ${detailsId}` : detailsId,\n );\n\n return () => {\n if (previous === null) {\n trigger.removeAttribute(\"aria-details\");\n } else {\n trigger.setAttribute(\"aria-details\", previous);\n }\n };\n }, [isOpen, triggerRef, detailsId]);\n\n // Escape closes it. react-aria would do this through `useOverlay`, which is\n // part of the machinery this component leaves out.\n useEffect(() => {\n if (!isOpen) {\n return;\n }\n\n const closeOnEscape = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n onOpenChange(false);\n }\n };\n\n document.addEventListener(\"keydown\", closeOnEscape);\n return () => document.removeEventListener(\"keydown\", closeOnEscape);\n }, [isOpen, onOpenChange]);\n\n return (\n <div\n {...rest}\n {...overlayProps}\n id={id}\n ref={overlayRef}\n className={clsx(className, styles[\"non-modal\"])}\n data-placement={placement ?? undefined}\n data-entering={isEntering || undefined}\n data-exiting={isExiting || undefined}\n style={{\n ...overlayProps.style,\n /*\n * Two things `useOverlayPosition` adds for an overlay portalled to the\n * end of `<body>` and pinned to the viewport. This one renders where it\n * stands and scrolls with the page, so both are wrong here.\n *\n * `z-index: 100000` would put it in front of the whole application — it\n * scrolled over the docs site's sticky header. Dropping the value here\n * hands the level to CSS, where `.non-modal` claims the lowest one that\n * still clears ordinary page content.\n *\n * The `max-height` it caps the overlay at is wrong here for the same\n * reason, but it is written straight onto the element and has to be\n * undone in CSS — see `.non-modal` in Popover.module.scss.\n */\n zIndex: undefined,\n ...popoverWidthStyle(width),\n ...(isPositioned ? {} : { visibility: \"hidden\" }),\n }}\n >\n {withTip && (\n <div\n {...arrowProps}\n ref={arrowRef}\n className={styles.tip}\n data-placement={placement ?? undefined}\n style={{\n // What <Aria.OverlayArrow /> contributes on top of `arrowProps`:\n // it lifts the tip out of the flow and centres it on the anchor.\n position: \"absolute\",\n transform:\n placement === \"top\" || placement === \"bottom\"\n ? \"translateX(-50%)\"\n : \"translateY(-50%)\",\n // `arrowProps.style` carries the offset along the popover's edge and\n // leaves the other axis `undefined` — which still overwrites. So the\n // edge the tip sits on is set last: spread first, it silently lost\n // `top: 100%` and the tip jumped to the popover's top edge, pointing\n // away from an anchor that was below it.\n ...arrowProps.style,\n ...(placement ? { [placement]: \"100%\" } : {}),\n }}\n >\n <svg\n className={styles.tipIcon}\n width={16}\n height={16}\n viewBox=\"0 0 16 16\"\n >\n <path d=\"M0 0 L8 8 L16 0\" />\n </svg>\n </div>\n )}\n <div className={styles.content} id={detailsId}>\n {children}\n </div>\n </div>\n );\n};\n\nexport default NonModalPopoverContent;\n"],"mappings":"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"}
@@ -18,6 +18,7 @@ var ProgressBar_module_default = {
18
18
  value,
19
19
  bar,
20
20
  fill,
21
+ "progress-bar-fill": "flow--progress-bar--progress-bar-fill",
21
22
  "size-s": "flow--progress-bar--size-s",
22
23
  "size-m": "flow--progress-bar--size-m",
23
24
  "size-l": "flow--progress-bar--size-l",
@@ -1 +1 @@
1
- {"version":3,"file":"ProgressBar.module.mjs","names":[],"sources":["../../../../../../../src/components/ProgressBar/ProgressBar.module.scss"],"sourcesContent":[".progressBar {\n display: grid;\n grid-template-areas:\n \"label value\"\n \"bar bar\";\n grid-template-columns: 1fr auto;\n column-gap: var(--progress-bar--spacing-x);\n width: 100%;\n font-size: var(--progress-bar--font-size);\n\n @extend .size-m;\n @extend .info;\n\n &:has(.legend) {\n grid-template-areas:\n \"label value\"\n \"bar bar\"\n \"legend legend\";\n }\n\n /* Elements */\n\n .label {\n grid-area: label;\n }\n\n .value {\n grid-area: value;\n font-weight: var(--progress-bar--value-font-weight);\n }\n\n .bar {\n grid-area: bar;\n border-radius: var(--progress-bar--corner-radius);\n background-color: var(--progress-bar--background-color);\n box-shadow: inset 0 0 0 var(--progress-bar--border-width)\n var(--progress-bar--border-color);\n overflow: hidden;\n margin-top: var(--progress-bar--spacing-y);\n }\n\n .fill {\n height: 100%;\n display: flex;\n }\n\n .legend {\n grid-area: legend;\n margin-top: var(--progress-bar--spacing-bar-to-legend);\n }\n\n /* Size */\n\n &.size-s {\n font-size: var(--progress-bar--font-size-s);\n }\n\n /* Sizes */\n\n @mixin size($size) {\n &.size-#{$size} {\n .bar {\n height: var(--progress-bar--height--#{$size});\n }\n }\n }\n\n @include size(s);\n @include size(m);\n @include size(l);\n\n /* Variants */\n\n @mixin status($status) {\n &.#{$status} {\n .fill {\n background: var(--progress-bar--#{$status}-fill-background-color);\n }\n }\n }\n\n @include status(info);\n @include status(success);\n @include status(danger);\n @include status(warning);\n}\n"],"mappings":""}
1
+ {"version":3,"file":"ProgressBar.module.mjs","names":[],"sources":["../../../../../../../src/components/ProgressBar/ProgressBar.module.scss"],"sourcesContent":[".progressBar {\n display: grid;\n grid-template-areas:\n \"label value\"\n \"bar bar\";\n grid-template-columns: 1fr auto;\n column-gap: var(--progress-bar--spacing-x);\n width: 100%;\n font-size: var(--progress-bar--font-size);\n\n @extend .size-m;\n @extend .info;\n\n &:has(.legend) {\n grid-template-areas:\n \"label value\"\n \"bar bar\"\n \"legend legend\";\n }\n\n /* Elements */\n\n .label {\n grid-area: label;\n }\n\n .value {\n grid-area: value;\n font-weight: var(--progress-bar--value-font-weight);\n }\n\n .bar {\n grid-area: bar;\n border-radius: var(--progress-bar--corner-radius);\n background-color: var(--progress-bar--background-color);\n box-shadow: inset 0 0 0 var(--progress-bar--border-width)\n var(--progress-bar--border-color);\n overflow: hidden;\n margin-top: var(--progress-bar--spacing-y);\n }\n\n .fill {\n height: 100%;\n display: flex;\n animation: progress-bar-fill var(--progress-bar--transition-duration) ease;\n }\n\n .legend {\n grid-area: legend;\n margin-top: var(--progress-bar--spacing-bar-to-legend);\n }\n\n /* Size */\n\n &.size-s {\n font-size: var(--progress-bar--font-size-s);\n }\n\n /* Sizes */\n\n @mixin size($size) {\n &.size-#{$size} {\n .bar {\n height: var(--progress-bar--height--#{$size});\n }\n }\n }\n\n @include size(s);\n @include size(m);\n @include size(l);\n\n /* Variants */\n\n @mixin status($status) {\n &.#{$status} {\n .fill {\n background: var(--progress-bar--#{$status}-fill-background-color);\n }\n }\n }\n\n @include status(info);\n @include status(success);\n @include status(danger);\n @include status(warning);\n}\n\n/* The implicit \"to\" keyframe picks up the fill's inline width. */\n@keyframes progress-bar-fill {\n from {\n width: 0%;\n }\n}\n"],"mappings":""}
@@ -4326,6 +4326,10 @@ var all_dark_default = {
4326
4326
  "path": ["big-number", "font-weight"]
4327
4327
  }
4328
4328
  },
4329
+ "cartesian-chart": { "transition-duration": {
4330
+ "value": "800ms",
4331
+ "path": ["cartesian-chart", "transition-duration"]
4332
+ } },
4329
4333
  "cartesian-grid": {
4330
4334
  "color": {
4331
4335
  "value": "#E5EFF8",
@@ -4341,6 +4345,10 @@ var all_dark_default = {
4341
4345
  "path": ["chart-tooltip", "spacing"]
4342
4346
  } },
4343
4347
  "donut-chart": {
4348
+ "transition-duration": {
4349
+ "value": "800ms",
4350
+ "path": ["donut-chart", "transition-duration"]
4351
+ },
4344
4352
  "border-color": {
4345
4353
  "value": "#DCE9F7",
4346
4354
  "path": ["donut-chart", "border-color"]
@@ -5302,6 +5310,10 @@ var all_dark_default = {
5302
5310
  "path": ["password-creation-field", "rule-to-rule-spacing"]
5303
5311
  } },
5304
5312
  "progress-bar": {
5313
+ "transition-duration": {
5314
+ "value": "800ms",
5315
+ "path": ["progress-bar", "transition-duration"]
5316
+ },
5305
5317
  "font-size": {
5306
5318
  "value": "1rem",
5307
5319
  "path": ["progress-bar", "font-size"]