import Elementary import ElementaryHTMX import SharedModels extension HTMLAttribute.hx { @Sendable static func get(route: SiteRoute.View) -> HTMLAttribute { get(SiteRoute.View.router.path(for: route)) } @Sendable static func patch(route: SiteRoute.View) -> HTMLAttribute { patch(SiteRoute.View.router.path(for: route)) } @Sendable static func post(route: SiteRoute.View) -> HTMLAttribute { post(SiteRoute.View.router.path(for: route)) } @Sendable static func put(route: SiteRoute.View) -> HTMLAttribute { put(SiteRoute.View.router.path(for: route)) } @Sendable static func delete(route: SiteRoute.Api) -> HTMLAttribute { delete(SiteRoute.Api.router.path(for: route)) } } extension HTMLAttribute.hx { @Sendable static func target(_ target: HXTarget) -> HTMLAttribute { Self.target(target.selector) } } extension HTMLAttribute.hx where Tag: HTMLTrait.Attributes.Global { @Sendable static func on(_ event: HXOnEvent, value: String) -> HTMLAttribute { HTMLAttribute.custom(name: "hx-on::\(event.rawValue)", value: value) } @Sendable static func on(_ event: HXOnEvent, _ value: HXOnValue) -> HTMLAttribute { on(event, value: value.value) } @Sendable static func on(_ event: HXOnEvent, _ values: HXOnValue...) -> HTMLAttribute { on(event, value: values.value) } } enum HXOnEvent: String, Sendable { case afterRequest = "after-request" } indirect enum HXOnValue: Sendable { case ifSuccessful([Self]) case resetForm case setWindowLocation(String) case toggleContent(id: String) @Sendable static func toggleContent(_ toggle: Toggle) -> Self { toggleContent(id: toggle.rawValue) } @Sendable static func setWindowLocation(to route: SiteRoute.View) -> Self { setWindowLocation(SiteRoute.View.router.path(for: route)) } @Sendable static func ifSuccessful(_ values: Self...) -> Self { .ifSuccessful(values) } fileprivate var value: String { switch self { case .resetForm: return "this.reset();" case let .toggleContent(toggle): return "toggleContent('\(toggle)');" case let .setWindowLocation(string): return "window.location.href='\(string)';" case let .ifSuccessful(values): return "if(event.detail.successful) \(values.value)" } } enum Toggle: String, Sendable { case float } } extension Array where Element == HXOnValue { var value: String { return map(\.value).joined(separator: " ") } } extension HTMLAttribute where Tag: HTMLTrait.Attributes.Global { @Sendable static func id(_ key: IDKey) -> Self { id(key.description) } } enum IDKey: CustomStringConvertible, Sendable { case branch(Branch) case employee(Employee) case float case purchaseOrder(PurchaseOrder? = nil) case user(User) case vendor(Vendor) var description: String { switch self { case let .branch(key): return "branch-\(key)" case let .employee(key): return "employee-\(key)" case .float: return "float" case let .purchaseOrder(key): guard let key else { return "purchase-order" } return "purchase-order-\(key)" case let .user(key): return "user-\(key)" case let .vendor(key): return "vendor-\(key)" } } enum Branch: CustomStringConvertible, Sendable { case list case form case row(id: VendorBranch.ID) var description: String { switch self { case .list: return "list" case .form: return "form" case let .row(id): return id.uuidString } } } enum Employee: CustomStringConvertible, Sendable { case table case row(id: SharedModels.Employee.ID) var description: String { switch self { case .table: return "table" case let .row(id): return "\(id)" } } } enum PurchaseOrder: CustomStringConvertible, Sendable { case content case row(id: SharedModels.PurchaseOrder.ID) case search case table var description: String { switch self { case .content: return "content" case let .row(id): return "\(id)" case .search: return "search" case .table: return "table" } } } enum User: CustomStringConvertible, Sendable { case form case row(id: SharedModels.User.ID) case table var description: String { switch self { case .form: return "form" case .table: return "table" case let .row(id): return "\(id)" } } } enum Vendor: CustomStringConvertible, Sendable { case form case row(id: SharedModels.Vendor.ID) var description: String { switch self { case .form: return "form" case let .row(id): return "\(id)" } } } } enum HXTarget: CustomStringConvertible, Sendable { case body case id(IDKey) case this var selector: String { switch self { case .body: return "body" case let .id(key): return "#\(key)" case .this: return "this" } } var description: String { selector } }