diff --git a/Sources/FioriSwiftUICore/Models/ModelDefinitions.swift b/Sources/FioriSwiftUICore/Models/ModelDefinitions.swift index 934749459..dc6512825 100644 --- a/Sources/FioriSwiftUICore/Models/ModelDefinitions.swift +++ b/Sources/FioriSwiftUICore/Models/ModelDefinitions.swift @@ -408,6 +408,8 @@ public protocol SingleStepModel { // sourcery: virtualPropAxis = "var axis: Axis = .horizontal" // sourcery: virtualPropStepsData = "var stepItems: [StepItem] = []" // sourcery: virtualPropIsPresented = "@State var isPresented: Bool = false" +// sourcery: virtualPropStepFrames = "@State var stepFrames: [String: CGRect] = [:]" +// sourcery: virtualPropScrollBounds = "@State var scrollBounds: CGRect = .zero" // sourcery: generated_component_composite public protocol StepProgressIndicatorModel: AnyObject { // sourcery: bindingProperty diff --git a/Sources/FioriSwiftUICore/Views/StepProgressIndicator/StepProgressIndicator+View.swift b/Sources/FioriSwiftUICore/Views/StepProgressIndicator/StepProgressIndicator+View.swift index 24ac640a4..b330a6f1f 100644 --- a/Sources/FioriSwiftUICore/Views/StepProgressIndicator/StepProgressIndicator+View.swift +++ b/Sources/FioriSwiftUICore/Views/StepProgressIndicator/StepProgressIndicator+View.swift @@ -43,15 +43,33 @@ extension StepProgressIndicator: View { @ViewBuilder var stepsContainer: some View { switch axis { case .horizontal: - ScrollView(.horizontal, showsIndicators: false) { - StepProgressIndicatorContainer(selection: _selection, - steps: steps) + ScrollViewReader { proxy in + ScrollView(.horizontal, showsIndicators: false) { + StepProgressIndicatorContainer(selection: _selection, + steps: steps) + .environment(\.stepFrames, $stepFrames) + .onChange(of: _selection.wrappedValue) { newValue in + if let currentFrame = stepFrames[newValue], + !scrollBounds.contains(currentFrame) + { + withAnimation { + proxy.scrollTo(newValue, anchor: .leading) + } + } + } + } + } + .coordinateSpace(name: "SPICoordinateSpace") + .frameReader(in: .local) { rect in + scrollBounds = rect } case .vertical: - ScrollView(.vertical, showsIndicators: false) { - StepProgressIndicatorContainer(selection: _selection, - steps: steps) - }.padding(20) + ScrollViewReader { _ in + ScrollView(.vertical, showsIndicators: false) { + StepProgressIndicatorContainer(selection: _selection, + steps: steps) + }.padding(20) + } } } diff --git a/Sources/FioriSwiftUICore/Views/StepProgressIndicator/StepsEnvironment.swift b/Sources/FioriSwiftUICore/Views/StepProgressIndicator/StepsEnvironment.swift index 5008a4939..a23503014 100644 --- a/Sources/FioriSwiftUICore/Views/StepProgressIndicator/StepsEnvironment.swift +++ b/Sources/FioriSwiftUICore/Views/StepProgressIndicator/StepsEnvironment.swift @@ -71,6 +71,17 @@ extension EnvironmentValues { } } +struct StepFramesKey: EnvironmentKey { + static let defaultValue: Binding<[String: CGRect]> = .constant([:]) +} + +extension EnvironmentValues { + var stepFrames: Binding<[String: CGRect]> { + get { self[StepFramesKey.self] } + set { self[StepFramesKey.self] = newValue } + } +} + extension View { func stepAxis(_ axis: Axis) -> some View { self.environment(\.stepAxis, axis) diff --git a/Sources/FioriSwiftUICore/Views/StepProgressIndicator/_DefaultSteps.swift b/Sources/FioriSwiftUICore/Views/StepProgressIndicator/_DefaultSteps.swift index 4cbfdc3c4..7a3ef8e84 100644 --- a/Sources/FioriSwiftUICore/Views/StepProgressIndicator/_DefaultSteps.swift +++ b/Sources/FioriSwiftUICore/Views/StepProgressIndicator/_DefaultSteps.swift @@ -36,6 +36,7 @@ public struct _DefaultSteps: IndexedViewContainer { selection: $selection, isSubstep: isSubstep, showLine: showLine) + .id(data.id) if !data.substeps.isEmpty { StepProgressIndicatorContainer(selection: $selection, steps: _DefaultSteps(stepItems: data.substeps, @@ -50,7 +51,8 @@ public struct _DefaultSteps: IndexedViewContainer { struct DefaultSingleStep: View { @Environment(\.dynamicTypeSize) var dynamicTypeSize @Environment(\.stepAxis) var stepAxis - + @Environment(\.stepFrames) var stepFrames + var stepItem: StepItem @Binding var selection: String var isSubstep: Bool = false @@ -71,10 +73,15 @@ struct DefaultSingleStep: View { } var body: some View { - if isSubstep { - singleSubstep() - } else { - singleStep() + Group { + if isSubstep { + singleSubstep() + } else { + singleStep() + } + } + .frameReader(in: .named("SPICoordinateSpace")) { rect in + stepFrames.wrappedValue[stepItem.id] = rect } } diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/StepProgressIndicator+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/StepProgressIndicator+API.generated.swift index fc3ac931e..c8d40cf5b 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/StepProgressIndicator+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/StepProgressIndicator+API.generated.swift @@ -8,6 +8,9 @@ public struct StepProgressIndicator let _title: Title let _action: ActionView