diff --git a/android_kmp/app-sample/.idea/caches/deviceStreaming.xml b/android_kmp/app-sample/.idea/caches/deviceStreaming.xml new file mode 100644 index 0000000..04e6f50 --- /dev/null +++ b/android_kmp/app-sample/.idea/caches/deviceStreaming.xml @@ -0,0 +1,1017 @@ + + + + + + \ No newline at end of file diff --git a/android_kmp/app-sample/.idea/gradle.xml b/android_kmp/app-sample/.idea/gradle.xml new file mode 100644 index 0000000..72cb247 --- /dev/null +++ b/android_kmp/app-sample/.idea/gradle.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/android_kmp/app-sample/.idea/migrations.xml b/android_kmp/app-sample/.idea/migrations.xml new file mode 100644 index 0000000..f8051a6 --- /dev/null +++ b/android_kmp/app-sample/.idea/migrations.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/android_kmp/app-sample/.idea/misc.xml b/android_kmp/app-sample/.idea/misc.xml new file mode 100644 index 0000000..3040d03 --- /dev/null +++ b/android_kmp/app-sample/.idea/misc.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/android_kmp/app-sample/.idea/runConfigurations.xml b/android_kmp/app-sample/.idea/runConfigurations.xml new file mode 100644 index 0000000..16660f1 --- /dev/null +++ b/android_kmp/app-sample/.idea/runConfigurations.xml @@ -0,0 +1,17 @@ + + + + + + \ No newline at end of file diff --git a/android_kmp/app-sample/.idea/workspace.xml b/android_kmp/app-sample/.idea/workspace.xml new file mode 100644 index 0000000..6ced158 --- /dev/null +++ b/android_kmp/app-sample/.idea/workspace.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + 1763425035519 + + + + \ No newline at end of file diff --git a/ios/craftd-swiftui/Sources/craftd-swiftui/data/model/progressBar/ProgressBarProperties.swift b/ios/craftd-swiftui/Sources/craftd-swiftui/data/model/progressBar/ProgressBarProperties.swift new file mode 100644 index 0000000..aa57143 --- /dev/null +++ b/ios/craftd-swiftui/Sources/craftd-swiftui/data/model/progressBar/ProgressBarProperties.swift @@ -0,0 +1,10 @@ +struct ProgressBarProperties: Decodable { + let text: String? + let alignment: CraftDAlign? + let textAlign: CraftDAlign? + let progressColor: String? + let textColor: String? + let progress: Double? + let height: Double? + let spaceBetween: Double? +} diff --git a/ios/craftd-swiftui/Sources/craftd-swiftui/presentation/builder/CraftDBuilderManager.swift b/ios/craftd-swiftui/Sources/craftd-swiftui/presentation/builder/CraftDBuilderManager.swift index 6019bd2..b4ec9a5 100644 --- a/ios/craftd-swiftui/Sources/craftd-swiftui/presentation/builder/CraftDBuilderManager.swift +++ b/ios/craftd-swiftui/Sources/craftd-swiftui/presentation/builder/CraftDBuilderManager.swift @@ -5,7 +5,8 @@ public class CraftDBuilderManager { add(builders: [ CraftDTextBuilder(), CraftDButtonBuilder(), - CraftDCheckBoxBuilder() + CraftDCheckBoxBuilder(), + CraftDProgressBarBuilder(), ]) } diff --git a/ios/craftd-swiftui/Sources/craftd-swiftui/presentation/ui/progressBar/CraftDProgressBar.swift b/ios/craftd-swiftui/Sources/craftd-swiftui/presentation/ui/progressBar/CraftDProgressBar.swift new file mode 100644 index 0000000..95ad1e8 --- /dev/null +++ b/ios/craftd-swiftui/Sources/craftd-swiftui/presentation/ui/progressBar/CraftDProgressBar.swift @@ -0,0 +1,145 @@ +import SwiftUI + +struct CraftDProgressBar: View { + let text: String + let textAlign: Alignment + let alignment: CraftDAlign + let progressColor: String + let textColor: String + let progress: Double + let height: CGFloat + let spaceBetween: CGFloat + let listener: CraftDViewListener + + init( + _ properties: ProgressBarProperties, + listener: @escaping CraftDViewListener + ) { + self.text = properties.text ?? "" + self.textAlign = properties.textAlign?.alignment ?? .center + self.progressColor = properties.progressColor ?? "#0000FF" + self.progress = properties.progress ?? 0.0 + self.height = CGFloat(properties.height ?? 0.0) + self.alignment = properties.alignment ?? .top + self.textColor = properties.textColor ?? "#000000" + self.spaceBetween = properties.spaceBetween ?? 0.0 + self.listener = listener + } + + @ViewBuilder + private var topAlignmentLayout: some View { + VStack(spacing: .zero) { + Text(text) + .font(.body) + .foregroundStyle(Color(hex: textColor)) + + GeometryReader { geometry in + ZStack(alignment: .leading) { + RoundedRectangle(cornerRadius: 16) + .stroke(Color.gray.opacity(0.6), lineWidth: 2) + .fill(Color.clear) + .frame(height: height) + + RoundedRectangle(cornerRadius: 16) + .fill(Color(hex: progressColor)) + .frame(width: geometry.size.width * progress, height: height) + .animation(.easeInOut, value: progress) + } + } + } + } + + @ViewBuilder + private var bottomAlignmentLayout: some View { + VStack(spacing: .zero) { + + GeometryReader { geometry in + ZStack(alignment: .leading) { + RoundedRectangle(cornerRadius: 16) + .stroke(Color.gray.opacity(0.6), lineWidth: 2) + .fill(Color.clear) + .frame(height: height) + + RoundedRectangle(cornerRadius: 16) + .fill(Color(hex: progressColor)) + .frame(width: geometry.size.width * progress, height: height) + .animation(.easeInOut, value: progress) + } + } + + Spacer() + .frame(height: spaceBetween) + + Text(text) + .font(.body) + .foregroundStyle(Color(hex: textColor)) + } + } + + @ViewBuilder + private var leadingAlignmentLayout: some View { + HStack(alignment: .top, spacing: .zero) { + Text(text) + .font(.body) + .foregroundStyle(Color(hex: textColor)) + + Spacer() + .frame(width: spaceBetween) + + GeometryReader { geometry in + ZStack(alignment: .leading) { + RoundedRectangle(cornerRadius: 16) + .stroke(Color.gray.opacity(0.6), lineWidth: 2) + .fill(Color.clear) + .frame(height: height) + + RoundedRectangle(cornerRadius: 16) + .fill(Color(hex: progressColor)) + .frame(width: geometry.size.width * progress, height: height) + .animation(.easeInOut, value: progress) + } + } + } + } + + @ViewBuilder + private var trailingAlignmentLayout: some View { + HStack(alignment: .top, spacing: .zero) { + + GeometryReader { geometry in + ZStack(alignment: .leading) { + RoundedRectangle(cornerRadius: 16) + .stroke(Color.gray.opacity(0.6), lineWidth: 2) + .fill(Color.clear) + .frame(height: height) + + RoundedRectangle(cornerRadius: 16) + .fill(Color(hex: progressColor)) + .frame(width: geometry.size.width * progress, height: height) + .animation(.easeInOut, value: progress) + } + } + + Spacer() + .frame(width: spaceBetween) + + Text(text) + .font(.body) + .foregroundStyle(Color(hex: textColor)) + } + } + + @ViewBuilder + private var content: some View { + switch alignment { + case .top, .center: topAlignmentLayout + case .bottom: bottomAlignmentLayout + case .left: leadingAlignmentLayout + case .right: trailingAlignmentLayout + } + } + + var body: some View { + content + } +} diff --git a/ios/craftd-swiftui/Sources/craftd-swiftui/presentation/ui/progressBar/CraftDProgressBarBuilder.swift b/ios/craftd-swiftui/Sources/craftd-swiftui/presentation/ui/progressBar/CraftDProgressBarBuilder.swift new file mode 100644 index 0000000..3b0446a --- /dev/null +++ b/ios/craftd-swiftui/Sources/craftd-swiftui/presentation/ui/progressBar/CraftDProgressBarBuilder.swift @@ -0,0 +1,19 @@ +// +// CraftDProgressBarBuilder.swift +// CraftDSwiftUI +// +// Created by Pedro Alvarez on 17/11/25. +// + +import SwiftUI + +class CraftDProgressBarBuilder: CraftDBuilder { + public func craft(model: SimpleProperties, listener: @escaping CraftDViewListener) -> any View { + do { + let properties = try model.decodeValue(ProgressBarProperties.self, using: decoder) + return CraftDProgressBar(properties, listener: listener) + } catch { + return EmptyView() + } + } +} diff --git a/ios/sample/CraftDSample/dynamic.json b/ios/sample/CraftDSample/dynamic.json index ac070ca..83081e9 100644 --- a/ios/sample/CraftDSample/dynamic.json +++ b/ios/sample/CraftDSample/dynamic.json @@ -373,5 +373,18 @@ } } } + }, + { + "key": "CraftDProgressBar", + "value": { + "text": "Loading...", + "alignment": "RIGHT", + "textAlign": "CENTER", + "progressColor": "#FFAA00", + "textColor": "#00FFBB", + "progress": 0.65, + "height": 12.0, + "spaceBetween": 32.0 + } } ]