Download this file
| 1 | import SwiftUI |
| 2 | |
| 3 | // Draft observation stays in these small views, away from the grid hierarchy. |
| 4 | struct SheetFormulaBar: View { |
| 5 | @Bindable var model: SheetModel |
| 6 | var formulaFocused: FocusState<Bool>.Binding |
| 7 | var body: some View { |
| 8 | HStack { |
| 9 | TextField("Cell or range", text: $model.rangeText).frame(width: 110).onSubmit { |
| 10 | model.selectRange() |
| 11 | }.accessibilityLabel("Cell or range, for example A1:B5") |
| 12 | Text("fx").foregroundStyle(.secondary) |
| 13 | TextField("Cell contents or formula", text: $model.draft).focused(formulaFocused).disabled( |
| 14 | !model.mayWrite || model.busy || !model.failedWrites.isEmpty |
| 15 | ) |
| 16 | .autocorrectionDisabled() |
| 17 | #if os(iOS) |
| 18 | .textInputAutocapitalization(.never) |
| 19 | #endif |
| 20 | .onSubmit { Task { await model.commit() } } |
| 21 | .onKeyPress(.escape) { |
| 22 | model.discard() |
| 23 | return .handled |
| 24 | } |
| 25 | .onKeyPress(.tab) { |
| 26 | Task { await model.commit(moveRight: true) } |
| 27 | return .handled |
| 28 | } |
| 29 | if model.dirty { |
| 30 | Button(sheetsMacString("Save")) { Task { await model.commit() } }.disabled(model.busy) |
| 31 | Button("Discard") { model.discard() }.disabled(model.busy) |
| 32 | } |
| 33 | }.textFieldStyle(.roundedBorder).padding(8) |
| 34 | } |
| 35 | } |
| 36 | |
| 37 | struct SheetStatusBar: View { |
| 38 | var model: SheetModel |
| 39 | var body: some View { |
| 40 | HStack { |
| 41 | Text(model.page?.Sheet.TabName ?? "Sheet") |
| 42 | Spacer() |
| 43 | if model.busy { ProgressView().controlSize(.small) } |
| 44 | Text(model.dirty ? "Unsaved cell edit" : model.notice) |
| 45 | Text(model.live).foregroundStyle(.secondary) |
| 46 | }.font(.caption).padding(8) |
| 47 | } |
| 48 | } |
| 49 | |