diff --git a/VDSSample.xcodeproj/project.pbxproj b/VDSSample.xcodeproj/project.pbxproj index 68d290b..c5fe10a 100644 --- a/VDSSample.xcodeproj/project.pbxproj +++ b/VDSSample.xcodeproj/project.pbxproj @@ -35,6 +35,7 @@ 1808BEBE2BA4479500129230 /* CarouselScrollbarViewConttroller.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1808BEBD2BA4479500129230 /* CarouselScrollbarViewConttroller.swift */; }; 1832AC5B2BA1347B008AE476 /* BreadcrumbsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1832AC5A2BA1347B008AE476 /* BreadcrumbsViewController.swift */; }; 186D13CD2BBA990800986B53 /* DropdownSelectViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 186D13CC2BBA990800986B53 /* DropdownSelectViewController.swift */; }; + 18A3F1302BD9332500498E4A /* CalendarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18A3F12F2BD9332500498E4A /* CalendarViewController.swift */; }; 440B84CC2BD8E98B004A732A /* TableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 440B84CB2BD8E98B004A732A /* TableViewController.swift */; }; 445BA07A29C088470036A7C5 /* NotificationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 445BA07929C088470036A7C5 /* NotificationViewController.swift */; }; 44604AD929CE1CF900E62B51 /* LineViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44604AD829CE1CF900E62B51 /* LineViewController.swift */; }; @@ -44,6 +45,7 @@ EA0D1C312A673F3500E5C127 /* RadioButtonViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA0D1C302A673F3500E5C127 /* RadioButtonViewController.swift */; }; EA0D1C332A673FD400E5C127 /* RadioButtonItemViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA0D1C322A673FD400E5C127 /* RadioButtonItemViewController.swift */; }; EA0FC2C12912DC5500DF80B4 /* TextLinkCaretViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA0FC2C02912DC5500DF80B4 /* TextLinkCaretViewController.swift */; }; + EA1758462BC8893700A5C0D9 /* DatePickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA1758452BC8893700A5C0D9 /* DatePickerViewController.swift */; }; EA21C5D82B600E4200CFC139 /* VDSTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = EA21C5D72B600E4200CFC139 /* VDSTokens.xcframework */; }; EA21C5D92B600E4200CFC139 /* VDSTokens.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = EA21C5D72B600E4200CFC139 /* VDSTokens.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; EA297A682A02F5320031ED56 /* TableViewTestController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA297A672A02F5320031ED56 /* TableViewTestController.swift */; }; @@ -130,6 +132,7 @@ 1808BEBD2BA4479500129230 /* CarouselScrollbarViewConttroller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselScrollbarViewConttroller.swift; sourceTree = ""; }; 1832AC5A2BA1347B008AE476 /* BreadcrumbsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BreadcrumbsViewController.swift; sourceTree = ""; }; 186D13CC2BBA990800986B53 /* DropdownSelectViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropdownSelectViewController.swift; sourceTree = ""; }; + 18A3F12F2BD9332500498E4A /* CalendarViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarViewController.swift; sourceTree = ""; }; 440B84CB2BD8E98B004A732A /* TableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableViewController.swift; sourceTree = ""; }; 445BA07929C088470036A7C5 /* NotificationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationViewController.swift; sourceTree = ""; }; 44604AD829CE1CF900E62B51 /* LineViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LineViewController.swift; sourceTree = ""; }; @@ -139,6 +142,7 @@ EA0D1C302A673F3500E5C127 /* RadioButtonViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButtonViewController.swift; sourceTree = ""; }; EA0D1C322A673FD400E5C127 /* RadioButtonItemViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButtonItemViewController.swift; sourceTree = ""; }; EA0FC2C02912DC5500DF80B4 /* TextLinkCaretViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextLinkCaretViewController.swift; sourceTree = ""; }; + EA1758452BC8893700A5C0D9 /* DatePickerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatePickerViewController.swift; sourceTree = ""; }; EA21C5D72B600E4200CFC139 /* VDSTokens.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = VDSTokens.xcframework; path = SharedFrameworks/VDSTokens.xcframework; sourceTree = ""; }; EA297A672A02F5320031ED56 /* TableViewTestController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableViewTestController.swift; sourceTree = ""; }; EA3C3B99289966EF000CA526 /* VDSSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = VDSSample.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -319,10 +323,12 @@ EAB5FEEE2927E28400998C17 /* ButtonGroupViewController.swift */, EA81410D2A0ED8DC004F60D2 /* ButtonIconViewController.swift */, 5FC35BE828D5235A004EBEAC /* ButtonViewController.swift */, + 18A3F12F2BD9332500498E4A /* CalendarViewController.swift */, 1808BEBD2BA4479500129230 /* CarouselScrollbarViewConttroller.swift */, EA89204D28B67332006B9984 /* CheckBoxGroupViewController.swift */, EAF7F09B2899B92400B287F5 /* CheckboxItemViewController.swift */, EA0D1C2E2A66CFE900E5C127 /* CheckboxViewController.swift */, + EA1758452BC8893700A5C0D9 /* DatePickerViewController.swift */, 186D13CC2BBA990800986B53 /* DropdownSelectViewController.swift */, EA985C00296CC21C00F2FF2E /* IconViewController.swift */, EAA5EEAC28EB6924003B3210 /* InputFieldViewController.swift */, @@ -518,6 +524,7 @@ EA3C3BB428996775000CA526 /* PickerBase.swift in Sources */, EAB2376C29E9E74900AABE9A /* TrailingTooltipLabelViewController.swift in Sources */, EAB1D2C928AAAA1D00DAE764 /* BaseViewController.swift in Sources */, + EA1758462BC8893700A5C0D9 /* DatePickerViewController.swift in Sources */, EAD062AD2A3B86950015965D /* BadgeIndicatorViewController.swift in Sources */, EA5E305C295111050082B959 /* TileletViewController.swift in Sources */, EAD062A32A3913920015965D /* DropShawdowViewController.swift in Sources */, @@ -532,6 +539,7 @@ 71B23C312B921D740027F7D9 /* PaginationViewController.swift in Sources */, EAF7F09C2899B92400B287F5 /* CheckboxItemViewController.swift in Sources */, EA0D1C2F2A66CFE900E5C127 /* CheckboxViewController.swift in Sources */, + 18A3F1302BD9332500498E4A /* CalendarViewController.swift in Sources */, EA596ABA2A16B2ED00300C4B /* TabsViewController.swift in Sources */, EA89204E28B67332006B9984 /* CheckBoxGroupViewController.swift in Sources */, EAA5EEAD28EB6924003B3210 /* InputFieldViewController.swift in Sources */, @@ -696,7 +704,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 60; + CURRENT_PROJECT_VERSION = 64; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = FCMA4QKS77; GENERATE_INFOPLIST_FILE = YES; @@ -731,7 +739,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 60; + CURRENT_PROJECT_VERSION = 64; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = FCMA4QKS77; GENERATE_INFOPLIST_FILE = YES; diff --git a/VDSSample/Extensions/IconName.swift b/VDSSample/Extensions/IconName.swift index 8dc6b69..f9b71dd 100644 --- a/VDSSample/Extensions/IconName.swift +++ b/VDSSample/Extensions/IconName.swift @@ -62,7 +62,6 @@ extension Icon.Name { public static let bucketTruck = Icon.Name(name: "bucket-truck") public static let bug = Icon.Name(name: "bug") public static let businessContinuity = Icon.Name(name: "business-continuity") - public static let calendar = Icon.Name(name: "calendar") public static let calibrate = Icon.Name(name: "calibrate") public static let callDisconnected = Icon.Name(name: "call-disconnected") public static let callerId = Icon.Name(name: "caller-id") @@ -152,7 +151,6 @@ extension Icon.Name { public static let error = Icon.Name(name: "error") public static let euro = Icon.Name(name: "euro") public static let expense = Icon.Name(name: "expense") - public static let externalLink = Icon.Name(name: "external-link") public static let faceCovering = Icon.Name(name: "face-covering") public static let facebook = Icon.Name(name: "facebook") public static let fallDetected = Icon.Name(name: "fall-detected") @@ -517,5 +515,5 @@ extension Icon.Name { public static let zoomIn = Icon.Name(name: "zoom-in") public static let zoomOut = Icon.Name(name: "zoom-out") static let all: [Icon.Name] = [ - threedAd, accessibility, accessories, adTechStack, adaptiveSpeaker, addFolder, addToFavorite, addUser, addedToFavorite, advancedSettings, agentChat, agricultureLeaves, agricultureTractor, agricultureVineyard, aiDashcam, airConditioner, airport, alertNotification, ambulance, americanSignLanguage, analytics, announcement, ar, archive, artboard, assetTracking, assistedListeningSystems, at, attach, audienceTargetedSearch, audioDescription, award, awareness, babyMonitor, barcode, battery, bestPractices, bid, billDown, billUp, blind, bluetooth, bonusData, bookmark, bot, boxOpen, braille, brightness, bringYourOwnDevice, bucketTruckBoom, bucketTruck, bug, businessContinuity, calendar, calibrate, callDisconnected, callerId, camera, carBattery, carryoverData, cellPhone, cellTower, chat, checkmark, cleanSurface, clock, closeAlternate, close, closedCaptioning, cloudDocument, cloud, coffee, cognitiveDisability, coin, comparison, compass, complianceDocument, compose, conditionBasedMaintenance, conditionBasedWrench, connectParts, connect, constructionHammer, constructionTruck, consultativeTransfer, convergence, conversion, countDown, creditCard, crop, crossDeviceTargeting, crossDevice, cta, ctr, customAudience, customize, dataBoost, data, deaf, decrease, deviceActivity, deviceProtection, devicesAddons, dfcVideoSideBySide, diagnostic, digitalContent, digitalSignageCar, digitalSignage, dining, directCarrierBilling, directory, displayUtilities, display, distribution, domainTargeting, doorbell, downArrow, downCaret, download, dragAndDrop, driver, droneCamera, dropShipment, duplicate, edit, educationCurriculum, education, electricCar, electricPower, electricUtility, electricVan, emailSignature, email, embeddedSound, emergencyContact, emoji, employeeTermination, energyScience, energyUtilities, enterprise, error, euro, expense, externalLink, faceCovering, facebook, fallDetected, favorite, fax, federalDefense, feedback, filterOff, filter, financial, findMyRemote, fineArt, fingerprintSensor, fire, fitToZone, flag, fleetTracking, fleet, flexibilityRectangles, flexibility, flipCamera, flurry, forwardedCall, fridge, fullscreen, gaming, gas, gateway, geofence, getHelp, gift, giftedData, government, gridView, groupFamily, growthOpportunities, growth, hackers, handshake, healthcareCorporate, healthcareGeneral, healthcareWorker, history, homeInternet, home, humidity, ideasSolutions, identityGraph, impressionVideo, inStorePickup, inclusivity, incomingCall, increase, industry, inferredIdentity, info, instagram, insurance, intelligentTracking, internationalLongDistance, internationalSymbolOfAccess, international, internetDevices, internetOfThings, inventory, invitationAccepted, invitationExpired, invitationRejected, irobot, ironingBoard, joinCall, k12Education, kidsStroller, landscape, laptopAntivirus, laptopControls, laptopGpsTracking, laptopSettings, laptopTrends, laptopWireless, largePlan, law, leftArrow, leftCaret, levers, light, link, list, liveCaption, lmr, loanerEquipment, locationPin, location, lockClosed, lockOpen, logout, loyaltyRetention, manufacturing, mapView, masonryView, maximize, medal, mediaEntertainment, mediumBusiness, mediumPlan, menu, mergeCalls, microphone, minus, missedCall, mobileApps, mobileCommandCenter, mobileHotspot, mobileKioskInfo, mobileKioskWireless, mobilePlusTv, mobileRetail, mobileRetargeting, mobileSearch, mobileWorkforceManagement, moreHorizontal, motionDetector, moveTo, multicast, multipleDeviceProtection, multipleDevices, multipleDocuments, music, mute, myAccount, nationwide, nativeVideo, native, networkAttachedStorage, networkConnection, network, news, next, nfcTag, night, noFee, noOff, noSmoking, noVideo, no, notification, notificationsOff, notifyMe, officePhoneSystem, oilIndustry, onDemand, onGoCar, oneYear, openCaptioning, operationalTransformation, orders, outOfStock, outgoingCall, packBackpack, packLuggage, packPurse, paperFreeBilling, passenger, pauseInternet, pause, peelSticker, petsCollar, pharmaceutical, phoneAllGood, phoneFavorite, phoneMedical, phonePublicSafety, phoneVolume, phone, photo, platform, playWith, play, plus, policeFleet, portrait, pressure, previous, print, professionalServicesCase, professionalServicesChart, publicSafety, publicTransportation, purchaseData, pushNotification, pushToTalk, question, realTimeTracking, realTime, recycle, remindMe, reminder, removeItem, reoccurringPayment, replaceAPhoto, reply, reportsAndAlerts, research, reservations, responsibleBusiness, retailStore, retargeting, returns, rewards, rightArrow, rightCaret, ringing, ringtone, riskMonitor, router, rss, satelliteOff, satellite, save, scaleAlt, scale, schoolNotebook, search, securityAlert, securityCheck, securityKeyhole, securityWireless, sendMessage, serverClock, serverSearch, serverStack, setFallbackImage, setGalleryImage, settings, share, shipping, shock, shoppingBag, shopping, signalBroadcast, simCard, singleDocument, smallBusiness, smallPlan, smartAssistant, smartBoiler, smartCommunities, smartFamilyChildAddressBook, smartLighting, smartMeter, smartScooter, smartSocket, smartSwitch, smokeDetector, snooze, socialDistancing, solarPanel, sort, sound, speakerMute, speakerPhone, speedMonitoring, speed, sportsBike, sportsSkis, sportsSoccer, sportsTennis, stadiumFlag, stakeholder, star, steps, stethoscope, stockTogether, stopAlt, stop, supportDrawer, support, survey, swipeLeft, swipeRight, swipe, `switch`, sync, tabletData, tabletWireless, tablet, tag, talking, targetGoal, taxes, teamLeader, techLaptop, technology, telematicsCar, teletype, temperature, template, textToSpeech, theme, thermostatTech, thumbsDown, thumbsUp, ticket, tiles, tilt, timer, tireBlowout, tools, topBox, totalMobileProtection, towTruck, tradingDeck, trafficLight, traffic, trailers, training, transportation, trash, travelKeys, travelPass, tripPlanner, trumpet, turnOnOff, tvContent, tv, twitter, undo, unification, unlimitedPlan, upArrow, upCaret, uplink, upload, urlTransparency, userGuides1, userGuides2, userRegistration, userSettings, utilityGridManagement, vibration, videoOnTablet, video, virtualReality, visibility, voiceHd, voiceMail, volume, volunteer, warning, waterResistant, waterUtility, wearable, weather, webinar, weights, whiteboard, winchService, wirelessVending, wirelessVideoSurveillance, yield, youtube, zoomIn, zoomOut ] + threedAd, accessibility, accessories, adTechStack, adaptiveSpeaker, addFolder, addToFavorite, addUser, addedToFavorite, advancedSettings, agentChat, agricultureLeaves, agricultureTractor, agricultureVineyard, aiDashcam, airConditioner, airport, alertNotification, ambulance, americanSignLanguage, analytics, announcement, ar, archive, artboard, assetTracking, assistedListeningSystems, at, attach, audienceTargetedSearch, audioDescription, award, awareness, babyMonitor, barcode, battery, bestPractices, bid, billDown, billUp, blind, bluetooth, bonusData, bookmark, bot, boxOpen, braille, brightness, bringYourOwnDevice, bucketTruckBoom, bucketTruck, bug, businessContinuity, calendar, calibrate, callDisconnected, callerId, camera, carBattery, carryoverData, cellPhone, cellTower, chat, checkmark, cleanSurface, clock, closeAlternate, close, closedCaptioning, cloudDocument, cloud, coffee, cognitiveDisability, coin, comparison, compass, complianceDocument, compose, conditionBasedMaintenance, conditionBasedWrench, connectParts, connect, constructionHammer, constructionTruck, consultativeTransfer, convergence, conversion, countDown, creditCard, crop, crossDeviceTargeting, crossDevice, cta, ctr, customAudience, customize, dataBoost, data, deaf, decrease, deviceActivity, deviceProtection, devicesAddons, dfcVideoSideBySide, diagnostic, digitalContent, digitalSignageCar, digitalSignage, dining, directCarrierBilling, directory, displayUtilities, display, distribution, domainTargeting, doorbell, downArrow, downCaret, download, dragAndDrop, driver, droneCamera, dropShipment, duplicate, edit, educationCurriculum, education, electricCar, electricPower, electricUtility, electricVan, emailSignature, email, embeddedSound, emergencyContact, emoji, employeeTermination, energyScience, energyUtilities, enterprise, error, euro, expense, externalLink, faceCovering, facebook, fallDetected, favorite, fax, federalDefense, feedback, filterOff, filter, financial, findMyRemote, fineArt, fingerprintSensor, fire, fitToZone, flag, fleetTracking, fleet, flexibilityRectangles, flexibility, flipCamera, flurry, forwardedCall, fridge, fullscreen, gaming, gas, gateway, geofence, getHelp, gift, giftedData, government, gridView, groupFamily, growthOpportunities, growth, hackers, handshake, healthcareCorporate, healthcareGeneral, healthcareWorker, history, homeInternet, home, humidity, ideasSolutions, identityGraph, impressionVideo, inStorePickup, inclusivity, incomingCall, increase, industry, inferredIdentity, info, instagram, insurance, intelligentTracking, internationalLongDistance, internationalSymbolOfAccess, international, internetDevices, internetOfThings, inventory, invitationAccepted, invitationExpired, invitationRejected, irobot, ironingBoard, joinCall, k12Education, kidsStroller, landscape, laptopAntivirus, laptopControls, laptopGpsTracking, laptopSettings, laptopTrends, laptopWireless, largePlan, law, leftArrow, leftCaret, levers, light, link, list, liveCaption, lmr, loanerEquipment, locationPin, location, lockClosed, lockOpen, logout, loyaltyRetention, manufacturing, mapView, masonryView, maximize, medal, mediaEntertainment, mediumBusiness, mediumPlan, menu, mergeCalls, microphone, minus, missedCall, mobileApps, mobileCommandCenter, mobileHotspot, mobileKioskInfo, mobileKioskWireless, mobilePlusTv, mobileRetail, mobileRetargeting, mobileSearch, mobileWorkforceManagement, moreHorizontal, motionDetector, moveTo, multicast, multipleDeviceProtection, multipleDevices, multipleDocuments, music, mute, myAccount, nationwide, nativeVideo, native, networkAttachedStorage, networkConnection, network, news, next, nfcTag, night, noFee, noOff, noSmoking, noVideo, no, notification, notificationsOff, notifyMe, officePhoneSystem, oilIndustry, onDemand, onGoCar, oneYear, openCaptioning, operationalTransformation, orders, outOfStock, outgoingCall, packBackpack, packLuggage, packPurse, paperFreeBilling, passenger, pauseInternet, pause, peelSticker, petsCollar, pharmaceutical, phoneAllGood, phoneFavorite, phoneMedical, phonePublicSafety, phoneVolume, phone, photo, platform, playWith, play, plus, policeFleet, portrait, pressure, previous, print, professionalServicesCase, professionalServicesChart, publicSafety, publicTransportation, purchaseData, pushNotification, pushToTalk, question, realTimeTracking, realTime, recycle, remindMe, reminder, removeItem, reoccurringPayment, replaceAPhoto, reply, reportsAndAlerts, research, reservations, responsibleBusiness, retailStore, retargeting, returns, rewards, rightArrow, rightCaret, ringing, ringtone, riskMonitor, router, rss, satelliteOff, satellite, save, scaleAlt, scale, schoolNotebook, search, securityAlert, securityCheck, securityKeyhole, securityWireless, sendMessage, serverClock, serverSearch, serverStack, setFallbackImage, setGalleryImage, settings, share, shipping, shock, shoppingBag, shopping, signalBroadcast, simCard, singleDocument, smallBusiness, smallPlan, smartAssistant, smartBoiler, smartCommunities, smartFamilyChildAddressBook, smartLighting, smartMeter, smartScooter, smartSocket, smartSwitch, smokeDetector, snooze, socialDistancing, solarPanel, sort, sound, speakerMute, speakerPhone, speedMonitoring, speed, sportsBike, sportsSkis, sportsSoccer, sportsTennis, stadiumFlag, stakeholder, star, steps, stethoscope, stockTogether, stopAlt, stop, supportDrawer, support, survey, swipeLeft, swipeRight, swipe, `switch`, sync, tabletData, tabletWireless, tablet, tag, talking, targetGoal, taxes, teamLeader, techLaptop, technology, telematicsCar, teletype, temperature, template, textToSpeech, theme, thermostatTech, thumbsDown, thumbsUp, ticket, tiles, tilt, timer, tireBlowout, tools, topBox, totalMobileProtection, towTruck, tradingDeck, trafficLight, traffic, trailers, training, transportation, trash, travelKeys, travelPass, tripPlanner, trumpet, turnOnOff, tvContent, tv, twitter, undo, unification, unlimitedPlan, upArrow, upCaret, uplink, upload, urlTransparency, userGuides1, userGuides2, userRegistration, userSettings, utilityGridManagement, vibration, videoOnTablet, video, virtualReality, visibility, voiceHd, voiceMail, volume, volunteer, warning, waterResistant, waterUtility, wearable, weather, webinar, weights, whiteboard, winchService, wirelessVending, wirelessVideoSurveillance, yield, youtube, zoomIn, zoomOut] } diff --git a/VDSSample/Protocols/PickerBase.swift b/VDSSample/Protocols/PickerBase.swift index e0be6d6..3c38693 100644 --- a/VDSSample/Protocols/PickerBase.swift +++ b/VDSSample/Protocols/PickerBase.swift @@ -134,8 +134,15 @@ public class PickerSelectorView: UIStackView, Picker } private func title(for row: Int) -> String { - guard let item = items[row].rawValue as? String else { return "" } - return item + let item = items[row] + + if let item = item as? CustomStringConvertible { + return item.description + } else if let raw = item.rawValue as? String { + return raw + } else { + return "" + } } } diff --git a/VDSSample/Supporting Files/Resources/SVG.xcassets/external-link.imageset/Contents.json b/VDSSample/Supporting Files/Resources/SVG.xcassets/external-link.imageset/Contents.json deleted file mode 100644 index 1e10c5e..0000000 --- a/VDSSample/Supporting Files/Resources/SVG.xcassets/external-link.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "filename" : "external-link.svg", - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - }, - "properties" : { - "preserves-vector-representation" : true - } -} diff --git a/VDSSample/Supporting Files/Resources/SVG.xcassets/external-link.imageset/external-link.svg b/VDSSample/Supporting Files/Resources/SVG.xcassets/external-link.imageset/external-link.svg deleted file mode 100644 index 5c545b6..0000000 --- a/VDSSample/Supporting Files/Resources/SVG.xcassets/external-link.imageset/external-link.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/VDSSample/ViewControllers/BadgeIndicatorViewController.swift b/VDSSample/ViewControllers/BadgeIndicatorViewController.swift index f3e57f0..69f662a 100644 --- a/VDSSample/ViewControllers/BadgeIndicatorViewController.swift +++ b/VDSSample/ViewControllers/BadgeIndicatorViewController.swift @@ -52,6 +52,7 @@ class BadgeIndicatorViewController: BaseViewController { var textField = NumericField() var leadingCharacterTextField = TextField() + var accessibilityTextField = TextField() var trailingTextField = TextField() var hideDotSwitch = Toggle() var hideBorderSwitch = Toggle() @@ -85,7 +86,8 @@ class BadgeIndicatorViewController: BaseViewController { addFormRow(label: "Border Light", view: borderColorLightPickerSelectorView) addFormRow(label: "Border Dark", view: borderColorDarkPickerSelectorView) addFormRow(label: "Size", view: textSizePickerSelectorView) - + addFormRow(label: "Accessiblity Text", view: accessibilityTextField) + dotForm.addFormRow(label: "Hide Dot", view: hideDotSwitch) dotForm.addFormRow(label: "Dot Size", view: dotSizeTextField) numberedForm.addFormRow(label: "Leading Character", view: leadingCharacterTextField) @@ -122,6 +124,11 @@ class BadgeIndicatorViewController: BaseViewController { self?.component.trailingText = text }.store(in: &subscribers) + accessibilityTextField.textPublisher + .sink { [weak self] text in + self?.component.accessibilityText = text + }.store(in: &subscribers) + heightTextField .numberPublisher .sink { [weak self] number in diff --git a/VDSSample/ViewControllers/BaseViewController.swift b/VDSSample/ViewControllers/BaseViewController.swift index 46526d9..631eeac 100644 --- a/VDSSample/ViewControllers/BaseViewController.swift +++ b/VDSSample/ViewControllers/BaseViewController.swift @@ -43,7 +43,7 @@ public class FormSection: UIStackView { } @discardableResult - open func addFormRow(label: String, view: UIView) -> UIView { + open func addFormRow(label: String, tooltip: Tooltip.TooltipModel? = nil, view: UIView) -> UIView { let formRow = UIStackView().with { $0.translatesAutoresizingMaskIntoConstraints = false $0.alignment = .fill @@ -56,6 +56,10 @@ public class FormSection: UIStackView { $0.tag = 1 $0.text = label $0.textStyle = .bodyLarge + $0.numberOfLines = 0 + if let tooltip { + $0.addTooltip(tooltip) + } } formRow.addArrangedSubview(label) @@ -333,10 +337,10 @@ public class BaseViewController: UIViewController, Initable , } @discardableResult - open func addFormRow(label: String, view: UIView) -> UIView { - return formStackView.addFormRow(label: label, view: view) + open func addFormRow(label: String, tooltip: Tooltip.TooltipModel? = nil, view: UIView) -> UIView { + return formStackView.addFormRow(label: label,tooltip: tooltip, view: view) } - + var activeTextField: UITextField? /// Called once when a view is initialized and is used to Setup additional UI or other constants and configurations. diff --git a/VDSSample/ViewControllers/ButtonIconViewController.swift b/VDSSample/ViewControllers/ButtonIconViewController.swift index d7f17ed..1fae6a2 100644 --- a/VDSSample/ViewControllers/ButtonIconViewController.swift +++ b/VDSSample/ViewControllers/ButtonIconViewController.swift @@ -241,12 +241,12 @@ class ButtonIconViewController: BaseViewController { func setBadgeIndicatorModel() { if variantOneSwitch.isOn { if badgeIndicatorSwitch.isOn { - component.badgeIndicatorModel = ButtonIcon.BadgeIndicatorModel(kind: BadgeIndicator.Kind.simple, size: BadgeIndicator.Size.small) + component.badgeIndicatorModel = ButtonIcon.BadgeIndicatorModel(kind: BadgeIndicator.Kind.simple, size: BadgeIndicator.Size.small, accessibilityText: "Custom Text would go here by the developer") } else { component.badgeIndicatorModel = nil } } else { - component.badgeIndicatorModel = ButtonIcon.BadgeIndicatorModel(kind: BadgeIndicator.Kind.numbered, expandDirection: badgeIndicatorExpandDirectionPickerSelectorView.selectedItem, size: BadgeIndicator.Size.small, maximumDigits: BadgeIndicator.MaximumDigits.two, number: 999) + component.badgeIndicatorModel = ButtonIcon.BadgeIndicatorModel(kind: BadgeIndicator.Kind.numbered, expandDirection: badgeIndicatorExpandDirectionPickerSelectorView.selectedItem, size: BadgeIndicator.Size.small, maximumDigits: BadgeIndicator.MaximumDigits.two, number: 999, accessibilityText: "Custom Text would go here by the developer for the 999") } } } diff --git a/VDSSample/ViewControllers/CalendarViewController.swift b/VDSSample/ViewControllers/CalendarViewController.swift new file mode 100644 index 0000000..c334560 --- /dev/null +++ b/VDSSample/ViewControllers/CalendarViewController.swift @@ -0,0 +1,305 @@ +// +// CalendarViewController.swift +// VDSSample +// +// Created by Kanamarlapudi, Vasavi on 19/04/24. +// + +import Foundation +import UIKit +import VDS +import Combine +import VDSTokens + +class CalendarViewController: BaseViewController { + let label = Label() + var containerBorderSwitch = Toggle() + var hideCurrentDateIndicatorSwitch = Toggle() + var transparentBgSwitch = Toggle() + var indicatorOneSwitch = Toggle() + var indicatorTwoSwitch = Toggle() + var indicatorThreeSwitch = Toggle() + var clearActiveDatesSwitch = Toggle() + var clearInactiveDatesSwitch = Toggle() + var activeDatesField = TextField() + var inactiveDatesField = TextField() + var legendOneField = TextField() + var legendTwoField = TextField() + var legendThreeField = TextField() + + private var minDatePicker: UIDatePicker = UIDatePicker() + private var maxDatePicker: UIDatePicker = UIDatePicker() + private var indicatorOnePicker: UIDatePicker = UIDatePicker() + private var indicatorTwoPicker: UIDatePicker = UIDatePicker() + private var indicatorThreePicker: UIDatePicker = UIDatePicker() + private var activeDatePicker: UIDatePicker = UIDatePicker().with { $0.datePickerMode = .date } + private var inactiveDatePicker: UIDatePicker = UIDatePicker().with { $0.datePickerMode = .date } + + var indicators: [CalendarBase.CalendarIndicatorModel] = [] + let indicatorOnePickerTag = 1 + let indicatorTwoPickerTag = 2 + let indicatorThreePickerTag = 3 + let minDatePickerTag = 4 + let maxDatePickerTag = 5 + let activeDatePickerTag = 6 + let inactiveDatePickerTag = 7 + + override func viewDidLoad() { + super.viewDidLoad() + addContentTopView(view: component) + component.minDate = Date().startOfMonth + component.maxDate = Date().endOfMonth + component.onChange = { [weak self] control in + self?.label.text = DateFormatter.localizedString(from: control.selectedDate, dateStyle: .short, timeStyle: .none) + } + minDatePicker.date = component.minDate + maxDatePicker.date = component.maxDate + setupPicker() + setupModel() + } + + override func setupForm() { + super.setupForm() + configurePicker(indicatorOnePicker) + indicatorOnePicker.tag = indicatorOnePickerTag + configurePicker(indicatorTwoPicker) + indicatorTwoPicker.tag = indicatorTwoPickerTag + configurePicker(indicatorThreePicker) + indicatorThreePicker.tag = indicatorThreePickerTag + configurePicker(minDatePicker) + minDatePicker.tag = minDatePickerTag + configurePicker(maxDatePicker) + maxDatePicker.tag = maxDatePickerTag + configurePicker(activeDatePicker) + activeDatePicker.tag = activeDatePickerTag + configurePicker(inactiveDatePicker) + inactiveDatePicker.tag = inactiveDatePickerTag + indicators = [ + .init(label: "Due Date", date: indicatorOnePicker.date), + .init(label: "Auto Pay", date: indicatorTwoPicker.date), + .init(label: "Scheduled", date: indicatorThreePicker.date) + ] + + //add form rows + addFormRow(label: "onChange", view: label) + addFormRow(label: "Surface", view: surfacePickerSelectorView) + addFormRow(label: "Hide Container Border", view: containerBorderSwitch) + addFormRow(label: "Hide Current Date Indicator", view: hideCurrentDateIndicatorSwitch) + addFormRow(label: "Min Date", view: minDatePicker) + addFormRow(label: "Max Date", view: maxDatePicker) + addFormRow(label: "Transparent Background", view: transparentBgSwitch) + addFormRow(label: "Active Dates", view: activeDatesField) + addFormRow(label: "Select ActiveDate", view: activeDatePicker) + addFormRow(label: "Clear Active Dates", view: clearActiveDatesSwitch) + addFormRow(label: "Inactive Dates", view: inactiveDatesField) + addFormRow(label: "Select InActiveDate", view: inactiveDatePicker) + addFormRow(label: "Clear Inactive Dates", view: clearInactiveDatesSwitch) + addFormRow(label: "Indicator One", view: indicatorOneSwitch) + addFormRow(label: "Indicator Two", view: indicatorTwoSwitch) + addFormRow(label: "Indicator Three", view: indicatorThreeSwitch) + addFormRow(label: "Legend One", view: legendOneField) + addFormRow(label: "Legend Two", view: legendTwoField) + addFormRow(label: "Legend Three", view: legendThreeField) + addFormRow(label: "Indicator One Date", view: indicatorOnePicker) + addFormRow(label: "Indicator Two Date", view: indicatorTwoPicker) + addFormRow(label: "Indicator Three Date", view: indicatorThreePicker) + activeDatesField.isUserInteractionEnabled = false + inactiveDatesField.isUserInteractionEnabled = false + activeDatesField.isEnabled = false + inactiveDatesField.isEnabled = false + + containerBorderSwitch.onChange = { [weak self] sender in + guard let self else { return } + component.hideContainerBorder = sender.isOn + } + + hideCurrentDateIndicatorSwitch.onChange = { [weak self] sender in + guard let self else { return } + component.hideCurrentDateIndicator = sender.isOn + } + + transparentBgSwitch.onChange = { [weak self] sender in + guard let self else { return } + component.transparentBackground = sender.isOn + } + + clearActiveDatesSwitch.onChange = { [weak self] sender in + guard let self else { return } + if sender.isOn { + activeDatesField.text = "" + component.activeDates = [] + } + } + + clearInactiveDatesSwitch.onChange = { [weak self] sender in + guard let self else { return } + if sender.isOn { + inactiveDatesField.text = "" + component.inactiveDates = [] + } + } + + legendOneField + .textPublisher + .sink { + [weak self] text in + self?.updateIndicatorData(label: text, date: self?.indicatorOnePicker.date, index: 0) + }.store(in: &subscribers) + + legendTwoField + .textPublisher + .sink { + [weak self] text in + self?.updateIndicatorData(label: text, date: self?.indicatorTwoPicker.date, index: 1) + }.store(in: &subscribers) + + legendThreeField + .textPublisher + .sink { + [weak self] text in + self?.updateIndicatorData(label: text, date: self?.indicatorThreePicker.date, index: 2) + }.store(in: &subscribers) + + indicatorOneSwitch.onChange = { [weak self] sender in + guard let self else { return } + if !sender.isOn { + component.indicators.removeAll() + } else { + self.setIndicatorsData() + } + } + + indicatorTwoSwitch.onChange = { [weak self] sender in + guard let self else { return } + if !sender.isOn { + if component.indicators.count > 2 { + component.indicators.removeLast() + component.indicators.removeLast() + } else if component.indicators.count == 2 { + component.indicators.removeLast() + } + } else { + self.setIndicatorsData() + } + + } + + indicatorThreeSwitch.onChange = { [weak self] sender in + guard let self else { return } + if !sender.isOn { + if component.indicators.count > 2 { + component.indicators.removeLast() + } + } else { + self.setIndicatorsData() + } + } + } + + func setupPicker(){ + surfacePickerSelectorView.onPickerDidSelect = { [weak self] item in + self?.component.surface = item + self?.contentTopView.backgroundColor = item.color + } + } + + func setupModel() { + let calendar = Calendar.current + let indicatorDate = calendar.startOfDay(for: calendar.date(byAdding: .day, value: 1, to: Date())!) + component.indicators = indicators + legendOneField.text = "Due Date" + legendTwoField.text = "Auto Pay" + legendThreeField.text = "Scheduled" + indicatorOneSwitch.isOn = true + indicatorTwoSwitch.isOn = true + indicatorThreeSwitch.isOn = true + hideCurrentDateIndicatorSwitch.isOn = false + indicatorOnePicker.date = indicatorDate + indicatorTwoPicker.date = indicatorDate + indicatorThreePicker.date = indicatorDate + updateIndicatorData(label: legendOneField.text ?? "", date: indicatorOnePicker.date, index: 0) + updateIndicatorData(label: legendTwoField.text ?? "", date: indicatorTwoPicker.date, index: 1) + updateIndicatorData(label: legendThreeField.text ?? "", date: indicatorThreePicker.date, index: 2) + } + + func updateIndicatorData(label: String = "", date: Date?, index:Int) { + indicators[index].label = label + indicators[index].date = date ?? Date() + setIndicatorsData() + } + + func setIndicatorsData() { + if indicatorOneSwitch.isOn && indicatorTwoSwitch.isOn && indicatorThreeSwitch.isOn { + component.indicators = [ + .init(label: self.legendOneField.text ?? "", date: indicatorOnePicker.date), + .init(label: self.legendTwoField.text ?? "", date: indicatorTwoPicker.date), + .init(label: self.legendThreeField.text ?? "", date: indicatorThreePicker.date) + ] + } else if indicatorOneSwitch.isOn && indicatorTwoSwitch.isOn && !indicatorThreeSwitch.isOn { + component.indicators = [ + .init(label: self.legendOneField.text ?? "", date: indicatorOnePicker.date), + .init(label: self.legendTwoField.text ?? "", date: indicatorTwoPicker.date), + ] + + } else if indicatorOneSwitch.isOn && !indicatorTwoSwitch.isOn { + component.indicators = [ + .init(label: self.legendOneField.text ?? "", date: indicatorOnePicker.date), + ] + } + } + + func configurePicker(_ sender:UIDatePicker) { + // Set some of UIDatePicker properties + sender.timeZone = NSTimeZone.local + sender.backgroundColor = UIColor.white + + // Add an event to call onDidChangeDate function when value is changed. + sender.addTarget(self, action: #selector(self.datePickerValueChanged(_:)), for: .valueChanged) + } + + @objc func datePickerValueChanged(_ sender: UIDatePicker){ + + switch sender.tag { + case indicatorOnePickerTag: + updateIndicatorData(label: legendOneField.text ?? "", date: sender.date, index: 0) + case indicatorTwoPickerTag: + updateIndicatorData(label: legendTwoField.text ?? "", date: sender.date, index: 1) + case indicatorThreePickerTag: + updateIndicatorData(label: legendThreeField.text ?? "", date: sender.date, index: 2) + case minDatePickerTag: + component.minDate = sender.date + case maxDatePickerTag: + component.maxDate = sender.date + case activeDatePickerTag: + component.activeDates.append(sender.date) + var text = activeDatesField.text + if let textEmpty = text?.isEmpty, textEmpty == true { + text?.append("") + } else { + text?.append(", ") + } + text?.append("\(self.getSelectedDate(with: sender.date))") + clearActiveDatesSwitch.isOn = false + activeDatesField.text = text + case inactiveDatePickerTag: + component.inactiveDates.append(sender.date) + var text = inactiveDatesField.text + if let textEmpty = text?.isEmpty, textEmpty == true { + text?.append("") + } else { + text?.append(", ") + } + text?.append("\(self.getSelectedDate(with: sender.date))") + clearInactiveDatesSwitch.isOn = false + inactiveDatesField.text = text + default: break + } + } + + func getSelectedDate(with date:Date) -> String { + let dateFormatter: DateFormatter = DateFormatter() + dateFormatter.dateFormat = "MM/dd/yyyy" + let day: String = dateFormatter.string(from: date) + return day + } +} diff --git a/VDSSample/ViewControllers/DatePickerViewController.swift b/VDSSample/ViewControllers/DatePickerViewController.swift new file mode 100644 index 0000000..3c5c460 --- /dev/null +++ b/VDSSample/ViewControllers/DatePickerViewController.swift @@ -0,0 +1,449 @@ +// +// DatePickerViewController.swift +// VDSSample +// +// Created by Matt Bruce on 4/11/24. +// + +import Foundation +import VDS +import UIKit + +class DatePickerViewController: BaseViewController { + + // Datepicker + var label = Label() + var disabledSwitch = Toggle() + var requiredSwitch = Toggle() + var labelTextField = TextField() + var errorTextField = TextField() + var helperTextField = TextField() + var inlineLabelSwitch = Toggle() + var readonlySwitch = Toggle() + var transparentBgSwitch = Toggle() + var errorSwitch = Toggle() + var widthTextField = NumericField() + var tooltipTitleTextField = TextField() + var tooltipContentTextField = TextField() + lazy var dateFormatPickerSelectorView = { + PickerSelectorView(title: "shortNumeric", + picker: self.picker, + items: DatePicker.DateFormat.allCases ) + }() + + // Calendar + //props + var indicators: [CalendarBase.CalendarIndicatorModel] = [] + var activeDates: [Date] = [] + var inactiveDates: [Date] = [] + var minDate: Date = Date().startOfMonth + var maxDate: Date = Date().endOfMonth + + //form + var containerBorderSwitch = Toggle() + var hideCurrentDateIndicatorSwitch = Toggle() + var indicatorOneSwitch = Toggle() + var indicatorTwoSwitch = Toggle() + var indicatorThreeSwitch = Toggle() + var clearActiveDatesSwitch = Toggle() + var clearInactiveDatesSwitch = Toggle() + var activeDatesField = TextField() + var inactiveDatesField = TextField() + var legendOneField = TextField() + var legendTwoField = TextField() + var legendThreeField = TextField() + + private var minDatePicker: UIDatePicker = UIDatePicker() + private var maxDatePicker: UIDatePicker = UIDatePicker() + private var indicatorOnePicker: UIDatePicker = UIDatePicker() + private var indicatorTwoPicker: UIDatePicker = UIDatePicker() + private var indicatorThreePicker: UIDatePicker = UIDatePicker() + private var activeDatePicker: UIDatePicker = UIDatePicker().with { $0.datePickerMode = .date } + private var inactiveDatePicker: UIDatePicker = UIDatePicker().with { $0.datePickerMode = .date } + + let indicatorOnePickerTag = 1 + let indicatorTwoPickerTag = 2 + let indicatorThreePickerTag = 3 + let minDatePickerTag = 4 + let maxDatePickerTag = 5 + let activeDatePickerTag = 6 + let inactiveDatePickerTag = 7 + + override func viewDidLoad() { + super.viewDidLoad() + addContentTopView(view: component) + setupModel() + setupPicker() + setupCalendar() + } + + override func setupForm(){ + addFormRow(label: "onChange", view: label) + addFormRow(label: "Surface", view: surfacePickerSelectorView) + addFormRow(label: "Disabled", view: disabledSwitch) + addFormRow(label: "Required", view: requiredSwitch) + addFormRow(label: "Date Format", view: dateFormatPickerSelectorView) + addFormRow(label: "Label Text", view: labelTextField) + addFormRow(label: "Helper Text", view: helperTextField) + addFormRow(label: "Readonly", view: readonlySwitch) + addFormRow(label: "Transparent Background", view: transparentBgSwitch) + addFormRow(label: "Error", view: .makeWrapper(for: errorSwitch)) + addFormRow(label: "Error Text", view: errorTextField) + addFormRow(label: "Width", view: widthTextField) + addFormRow(label: "ToolTip Title", view: tooltipTitleTextField) + addFormRow(label: "ToolTip Content", view: tooltipContentTextField) + append(section: getCalendarSection()) + disabledSwitch.onChange = { [weak self] sender in + self?.component.isEnabled = !sender.isOn + } + + requiredSwitch.onChange = { [weak self] sender in + self?.component.isRequired = sender.isOn + } + + readonlySwitch.onChange = { [weak self] sender in + self?.component.isReadOnly = sender.isOn + } + + transparentBgSwitch.onChange = { [weak self] sender in + self?.component.transparentBackground = sender.isOn + } + + errorSwitch + .publisher(for: .valueChanged) + .sink { [weak self] sender in + guard let self else { return } + component.showError = sender.isOn + if component.showError != sender.isOn { + self.errorSwitch.isOn = self.component.showError + } + }.store(in: &subscribers) + + labelTextField + .textPublisher + .sink { [weak self] text in + self?.component.labelText = text + }.store(in: &subscribers) + + helperTextField + .textPublisher + .sink { [weak self] text in + self?.component.helperText = text + }.store(in: &subscribers) + + errorTextField + .textPublisher + .sink { [weak self] text in + self?.component.errorText = text + }.store(in: &subscribers) + + widthTextField + .numberPublisher + .sink { [weak self] number in + self?.component.width = number?.cgFloatValue + }.store(in: &subscribers) + + tooltipTitleTextField + .textPublisher + .sink { [weak self] text in + self?.updateTooltip() + }.store(in: &subscribers) + + tooltipContentTextField + .textPublisher + .sink { [weak self] text in + self?.updateTooltip() + }.store(in: &subscribers) + + } + + func setupModel() { + component.selectedDate = Calendar.current.date(byAdding: .day, value: -5, to: Date()) + component.labelText = "Date" + component.helperText = "Pick a date for your needs." + component.errorText = "Enter a date." + component.tooltipModel = .init(title: "Check your date.", content:"Here is the content for your date component") + + component.onChange = { [weak self] control in + self?.label.text = DateFormatter.localizedString(from: control.selectedDate!, dateStyle: .short, timeStyle: .none) + } + + //setup UI + disabledSwitch.isOn = !component.isEnabled + requiredSwitch.isOn = component.isRequired + surfacePickerSelectorView.text = component.surface.rawValue + labelTextField.text = component.labelText + helperTextField.text = component.helperText + readonlySwitch.isOn = false + transparentBgSwitch.isOn = false + errorSwitch.isOn = component.showError + errorTextField.text = component.errorText + tooltipTitleTextField.text = component.tooltipModel?.title + tooltipContentTextField.text = component.tooltipModel?.content + } + + func setupPicker() { + surfacePickerSelectorView.onPickerDidSelect = { [weak self] item in + self?.component.surface = item + self?.contentTopView.backgroundColor = item.color + } + + dateFormatPickerSelectorView.onPickerDidSelect = { [weak self] item in + self?.component.dateFormat = item + } + + } + + func updateTooltip() { + let title = tooltipTitleTextField.text ?? "" + let content = tooltipContentTextField.text ?? "" + + component.tooltipModel = !title.isEmpty || !content.isEmpty ? .init(title: title, + content: content) : nil + } +} + +extension DatePickerViewController { + + func getCalendarSection() -> FormSection { + let section = FormSection() + section.title = "Calendar Options" + section.addFormRow(label: "Hide Container Border", view: containerBorderSwitch) + section.addFormRow(label: "Hide Current Date Indicator", view: hideCurrentDateIndicatorSwitch) + section.addFormRow(label: "Min Date", view: minDatePicker) + section.addFormRow(label: "Max Date", view: maxDatePicker) + section.addFormRow(label: "Active Dates", view: activeDatesField) + section.addFormRow(label: "Select ActiveDate", view: activeDatePicker) + section.addFormRow(label: "Clear Active Dates", view: clearActiveDatesSwitch) + section.addFormRow(label: "Inactive Dates", view: inactiveDatesField) + section.addFormRow(label: "Select InActiveDate", view: inactiveDatePicker) + section.addFormRow(label: "Clear Inactive Dates", view: clearInactiveDatesSwitch) + section.addFormRow(label: "Indicator One", view: indicatorOneSwitch) + section.addFormRow(label: "Indicator Two", view: indicatorTwoSwitch) + section.addFormRow(label: "Indicator Three", view: indicatorThreeSwitch) + section.addFormRow(label: "Legend One", view: legendOneField) + section.addFormRow(label: "Legend Two", view: legendTwoField) + section.addFormRow(label: "Legend Three", view: legendThreeField) + section.addFormRow(label: "Indicator One Date", view: indicatorOnePicker) + section.addFormRow(label: "Indicator Two Date", view: indicatorTwoPicker) + section.addFormRow(label: "Indicator Three Date", view: indicatorThreePicker) + + + containerBorderSwitch.onChange = { [weak self] sender in + self?.updateCalendarModel() + } + + hideCurrentDateIndicatorSwitch.onChange = { [weak self] sender in + self?.updateCalendarModel() + } + + clearActiveDatesSwitch.onChange = { [weak self] sender in + self?.updateCalendarModel() + } + + clearInactiveDatesSwitch.onChange = { [weak self] sender in + self?.updateCalendarModel() + } + + legendOneField + .textPublisher + .sink { + [weak self] text in + self?.updateIndicatorData(label: text, date: self?.indicatorOnePicker.date, index: 0) + }.store(in: &subscribers) + + legendTwoField + .textPublisher + .sink { + [weak self] text in + self?.updateIndicatorData(label: text, date: self?.indicatorTwoPicker.date, index: 1) + }.store(in: &subscribers) + + legendThreeField + .textPublisher + .sink { + [weak self] text in + self?.updateIndicatorData(label: text, date: self?.indicatorThreePicker.date, index: 2) + }.store(in: &subscribers) + + indicatorOneSwitch.onChange = { [weak self] sender in + guard let self else { return } + if !sender.isOn { + self.indicators.removeAll() + } else { + self.setIndicatorsData() + } + self.updateCalendarModel() + } + + indicatorTwoSwitch.onChange = { [weak self] sender in + guard let self else { return } + if !sender.isOn { + if self.indicators.count > 2 { + self.indicators.removeLast() + self.indicators.removeLast() + } else if self.indicators.count == 2 { + self.indicators.removeLast() + } + } else { + self.setIndicatorsData() + } + self.updateCalendarModel() + } + + indicatorThreeSwitch.onChange = { [weak self] sender in + guard let self else { return } + if !sender.isOn { + if self.indicators.count > 2 { + self.indicators.removeLast() + } + } else { + self.setIndicatorsData() + } + self.updateCalendarModel() + } + + return section + } + + func updateCalendarModel() { + component.calendarModel = .init(surface: component.surface, + hideContainerBorder: containerBorderSwitch.isOn, + hideCurrentDateIndicator: hideCurrentDateIndicatorSwitch.isOn, + activeDates: activeDates, + inactiveDates: inactiveDates, + minDate: minDate, + maxDate: maxDate, + indicators: indicators) + } + + func setupCalendar() { + configurePicker(indicatorOnePicker) + indicatorOnePicker.tag = indicatorOnePickerTag + configurePicker(indicatorTwoPicker) + indicatorTwoPicker.tag = indicatorTwoPickerTag + configurePicker(indicatorThreePicker) + indicatorThreePicker.tag = indicatorThreePickerTag + configurePicker(minDatePicker) + minDatePicker.tag = minDatePickerTag + configurePicker(maxDatePicker) + maxDatePicker.tag = maxDatePickerTag + configurePicker(activeDatePicker) + activeDatePicker.tag = activeDatePickerTag + configurePicker(inactiveDatePicker) + inactiveDatePicker.tag = inactiveDatePickerTag + indicators = [ + .init(label: "Due Date", date: indicatorOnePicker.date), + .init(label: "Auto Pay", date: indicatorTwoPicker.date), + .init(label: "Scheduled", date: indicatorThreePicker.date) + ] + + let calendar = Calendar.current + let indicatorDate = calendar.startOfDay(for: calendar.date(byAdding: .day, value: 1, to: Date())!) + legendOneField.text = "Due Date" + legendTwoField.text = "Auto Pay" + legendThreeField.text = "Scheduled" + indicatorOneSwitch.isOn = true + indicatorTwoSwitch.isOn = true + indicatorThreeSwitch.isOn = true + hideCurrentDateIndicatorSwitch.isOn = false + indicatorOnePicker.date = indicatorDate + indicatorTwoPicker.date = indicatorDate + indicatorThreePicker.date = indicatorDate + updateIndicatorData(label: legendOneField.text ?? "", date: indicatorOnePicker.date, index: 0) + updateIndicatorData(label: legendTwoField.text ?? "", date: indicatorTwoPicker.date, index: 1) + updateIndicatorData(label: legendThreeField.text ?? "", date: indicatorThreePicker.date, index: 2) + + activeDatesField.isUserInteractionEnabled = false + inactiveDatesField.isUserInteractionEnabled = false + activeDatesField.isEnabled = false + inactiveDatesField.isEnabled = false + + minDatePicker.date = minDate + maxDatePicker.date = maxDate + + updateCalendarModel() + } + + func updateIndicatorData(label: String = "", date: Date?, index:Int) { + indicators[index].label = label + indicators[index].date = date ?? Date() + updateCalendarModel() + } + + func setIndicatorsData() { + if indicatorOneSwitch.isOn && indicatorTwoSwitch.isOn && indicatorThreeSwitch.isOn { + indicators = [ + .init(label: self.legendOneField.text ?? "", date: indicatorOnePicker.date), + .init(label: self.legendTwoField.text ?? "", date: indicatorTwoPicker.date), + .init(label: self.legendThreeField.text ?? "", date: indicatorThreePicker.date) + ] + } else if indicatorOneSwitch.isOn && indicatorTwoSwitch.isOn && !indicatorThreeSwitch.isOn { + indicators = [ + .init(label: self.legendOneField.text ?? "", date: indicatorOnePicker.date), + .init(label: self.legendTwoField.text ?? "", date: indicatorTwoPicker.date), + ] + + } else if indicatorOneSwitch.isOn && !indicatorTwoSwitch.isOn { + indicators = [ + .init(label: self.legendOneField.text ?? "", date: indicatorOnePicker.date), + ] + } + } + + func configurePicker(_ sender:UIDatePicker) { + // Set some of UIDatePicker properties + sender.timeZone = NSTimeZone.local + sender.backgroundColor = UIColor.white + + // Add an event to call onDidChangeDate function when value is changed. + sender.addTarget(self, action: #selector(self.datePickerValueChanged(_:)), for: .valueChanged) + } + + @objc func datePickerValueChanged(_ sender: UIDatePicker){ + + switch sender.tag { + case indicatorOnePickerTag: + updateIndicatorData(label: legendOneField.text ?? "", date: sender.date, index: 0) + case indicatorTwoPickerTag: + updateIndicatorData(label: legendTwoField.text ?? "", date: sender.date, index: 1) + case indicatorThreePickerTag: + updateIndicatorData(label: legendThreeField.text ?? "", date: sender.date, index: 2) + case minDatePickerTag: + minDate = sender.date + case maxDatePickerTag: + maxDate = sender.date + case activeDatePickerTag: + activeDates.append(sender.date) + var text = activeDatesField.text + if let textEmpty = text?.isEmpty, textEmpty == true { + text?.append("") + } else { + text?.append(", ") + } + text?.append("\(self.getSelectedDate(with: sender.date))") + clearActiveDatesSwitch.isOn = false + activeDatesField.text = text + case inactiveDatePickerTag: + inactiveDates.append(sender.date) + var text = inactiveDatesField.text + if let textEmpty = text?.isEmpty, textEmpty == true { + text?.append("") + } else { + text?.append(", ") + } + text?.append("\(self.getSelectedDate(with: sender.date))") + clearInactiveDatesSwitch.isOn = false + inactiveDatesField.text = text + default: break + } + } + + func getSelectedDate(with date:Date) -> String { + let dateFormatter: DateFormatter = DateFormatter() + dateFormatter.dateFormat = "MM/dd/yyyy" + let day: String = dateFormatter.string(from: date) + return day + } + +} diff --git a/VDSSample/ViewControllers/DropShawdowViewController.swift b/VDSSample/ViewControllers/DropShawdowViewController.swift index 17d3733..9ef0b5d 100644 --- a/VDSSample/ViewControllers/DropShawdowViewController.swift +++ b/VDSSample/ViewControllers/DropShawdowViewController.swift @@ -34,9 +34,13 @@ class DropShadowViewController: BaseViewController { var componentWrapper: UIView! var componentConstraints: NSLayoutConstraint.Container! - var secondView = View() - var thirdView = View() + var secondView = ShadowView() + var thirdView = ShadowView() + var shadowViews: [ShadowView] { + [component, secondView, thirdView] + } + lazy var backgroundColorPickerSelectorView = { PickerSelectorView(title: "paletteWhite", picker: self.picker, @@ -125,8 +129,8 @@ class DropShadowViewController: BaseViewController { thirdView.width(viewSize).height(viewSize) componentWrapper.pinTop().pinLeading() - secondView.pinTop() - thirdView.pinLeading().pinBottom() + secondView.pinTop(VDSLayout.space2X) + thirdView.pinLeading(VDSLayout.space2X).pinBottom(VDSLayout.space2X) secondView.pinTrailingLessThanOrEqualTo(contentTopView.trailingAnchor) secondView.pinBottomLessThanOrEqualTo(contentTopView.bottomAnchor) @@ -194,7 +198,7 @@ class DropShadowViewController: BaseViewController { //shadow1 showShadow.publisher(for: .valueChanged).sink(receiveValue: { [weak self] slider in - self?.component.showShadow = slider.isOn + self?.shadowViews.forEach { $0.showShadow = slider.isOn } self?.updateView() }).store(in: &subscribers) @@ -202,7 +206,7 @@ class DropShadowViewController: BaseViewController { opacityRange.minimumValue = 0.0 opacityRange.value = 1.0 opacityRange.publisher(for: .valueChanged).sink(receiveValue: { [weak self] slider in - self?.component.opacityRange = CGFloat(slider.value) + self?.shadowViews.forEach { $0.opacityRange = CGFloat(slider.value) } self?.updateView() }).store(in: &subscribers) @@ -210,7 +214,7 @@ class DropShadowViewController: BaseViewController { radiusRange.minimumValue = 0.0 radiusRange.value = 2.0 radiusRange.publisher(for: .valueChanged).sink(receiveValue: { [weak self] slider in - self?.component.radiusRange = CGFloat(slider.value) + self?.shadowViews.forEach { $0.radiusRange = CGFloat(slider.value) } self?.updateView() }).store(in: &subscribers) @@ -218,7 +222,7 @@ class DropShadowViewController: BaseViewController { offsetXRange.minimumValue = -20 offsetXRange.value = 2.0 offsetXRange.publisher(for: .valueChanged).sink(receiveValue: { [weak self] slider in - self?.component.offsetXRange = CGFloat(slider.value) + self?.shadowViews.forEach { $0.offsetXRange = CGFloat(slider.value) } self?.updateView() }).store(in: &subscribers) @@ -226,13 +230,13 @@ class DropShadowViewController: BaseViewController { offsetYRange.minimumValue = -20 offsetYRange.value = 2.0 offsetYRange.publisher(for: .valueChanged).sink(receiveValue: { [weak self] slider in - self?.component.offsetYRange = CGFloat(slider.value) + self?.shadowViews.forEach { $0.offsetYRange = CGFloat(slider.value) } self?.updateView() }).store(in: &subscribers) //shadow2 showShadow2.publisher(for: .valueChanged).sink(receiveValue: { [weak self] slider in - self?.component.showShadow2 = slider.isOn + self?.shadowViews.forEach { $0.showShadow2 = slider.isOn } self?.updateView() }).store(in: &subscribers) @@ -240,7 +244,7 @@ class DropShadowViewController: BaseViewController { opacityRange2.minimumValue = 0.0 opacityRange2.value = 1.0 opacityRange2.publisher(for: .valueChanged).sink(receiveValue: { [weak self] slider in - self?.component.opacityRange2 = CGFloat(slider.value) + self?.shadowViews.forEach { $0.opacityRange2 = CGFloat(slider.value) } self?.updateView() }).store(in: &subscribers) @@ -248,7 +252,7 @@ class DropShadowViewController: BaseViewController { radiusRange2.minimumValue = 0.0 radiusRange2.value = 2.0 radiusRange2.publisher(for: .valueChanged).sink(receiveValue: { [weak self] slider in - self?.component.radiusRange2 = CGFloat(slider.value) + self?.shadowViews.forEach { $0.radiusRange2 = CGFloat(slider.value) } self?.updateView() }).store(in: &subscribers) @@ -256,7 +260,7 @@ class DropShadowViewController: BaseViewController { offsetXRange2.minimumValue = -20 offsetXRange2.value = 2.0 offsetXRange2.publisher(for: .valueChanged).sink(receiveValue: { [weak self] slider in - self?.component.offsetXRange2 = CGFloat(slider.value) + self?.shadowViews.forEach { $0.offsetXRange2 = CGFloat(slider.value) } self?.updateView() }).store(in: &subscribers) @@ -264,7 +268,7 @@ class DropShadowViewController: BaseViewController { offsetYRange2.minimumValue = -20 offsetYRange2.value = 2.0 offsetYRange2.publisher(for: .valueChanged).sink(receiveValue: { [weak self] slider in - self?.component.offsetYRange2 = CGFloat(slider.value) + self?.shadowViews.forEach { $0.offsetYRange2 = CGFloat(slider.value) } self?.updateView() }).store(in: &subscribers) @@ -281,7 +285,7 @@ class DropShadowViewController: BaseViewController { viewRadiusRange.minimumValue = 0 viewRadiusRange.value = 8.0 viewRadiusRange.publisher(for: .valueChanged).sink(receiveValue: { [weak self] slider in - self?.component.viewRadiusRange = CGFloat(slider.value) + self?.shadowViews.forEach { $0.viewRadiusRange = CGFloat(slider.value) } self?.updateView() }).store(in: &subscribers) @@ -310,8 +314,8 @@ class DropShadowViewController: BaseViewController { } override func updateView() { - secondView.backgroundColor = .red - thirdView.backgroundColor = .purple + secondView.viewLightColor = .paletteYellow53 + thirdView.viewLightColor = .paletteBlue46 } func setupPicker(){ @@ -322,20 +326,21 @@ class DropShadowViewController: BaseViewController { } dropShadowDarkColorPickerSelectorView.onPickerDidSelect = { [weak self] item in - self?.component.shadowDarkColor = item + self?.shadowViews.forEach { $0.shadowDarkColor = item } } dropShadowLightColorPickerSelectorView.onPickerDidSelect = { [weak self] item in - self?.component.shadowLightColor = item + self?.shadowViews.forEach { $0.shadowLightColor = item } } dropShadow2DarkColorPickerSelectorView.onPickerDidSelect = { [weak self] item in - self?.component.shadowDarkColor2 = item + self?.shadowViews.forEach { $0.shadowDarkColor2 = item } } dropShadow2LightColorPickerSelectorView.onPickerDidSelect = { [weak self] item in - self?.component.shadowLightColor2 = item + self?.shadowViews.forEach { $0.shadowLightColor2 = item } } + viewLightColorPickerSelectorView.onPickerDidSelect = { [weak self] item in self?.component.viewLightColor = item } diff --git a/VDSSample/ViewControllers/DropdownSelectViewController.swift b/VDSSample/ViewControllers/DropdownSelectViewController.swift index 52552c3..1d5002e 100644 --- a/VDSSample/ViewControllers/DropdownSelectViewController.swift +++ b/VDSSample/ViewControllers/DropdownSelectViewController.swift @@ -10,6 +10,12 @@ import VDS class DropdownSelectViewController: BaseViewController { + lazy var helperTextPlacementPickerSelectorView = { + PickerSelectorView(title: "", + picker: self.picker, + items: InputField.HelperTextPlacement.allCases) + }() + var disabledSwitch = Toggle() var requiredSwitch = Toggle() var labelTextField = TextField() @@ -21,6 +27,7 @@ class DropdownSelectViewController: BaseViewController { var errorSwitch = Toggle() var tooltipTitleTextField = TextField() var tooltipContentTextField = TextField() + var widthTextField = NumericField() var optionsSwitch = Toggle() var moreOptions: [DropdownSelect.DropdownOptionModel] = [ .init(text: "Alabama"), @@ -60,12 +67,14 @@ class DropdownSelectViewController: BaseViewController { addFormRow(label: "Disabled", view: disabledSwitch) addFormRow(label: "Required", view: requiredSwitch) addFormRow(label: "Label Text", view: labelTextField) + addFormRow(label: "Helper Text Placement", view: helperTextPlacementPickerSelectorView) addFormRow(label: "Helper Text", view: helperTextField) addFormRow(label: "Inline Label", view: .makeWrapper(for: inlineLabelSwitch)) addFormRow(label: "Readonly", view: readonlySwitch) addFormRow(label: "Transparent Background", view: transparentBgSwitch) addFormRow(label: "Error", view: .makeWrapper(for: errorSwitch)) addFormRow(label: "Error Text", view: errorTextField) + addFormRow(label: "Width", view: widthTextField) addFormRow(label: "ToolTip Title", view: tooltipTitleTextField) addFormRow(label: "ToolTip Content", view: tooltipContentTextField) addFormRow(label: "More Options", view: optionsSwitch) @@ -75,7 +84,7 @@ class DropdownSelectViewController: BaseViewController { } requiredSwitch.onChange = { [weak self] sender in - self?.component.required = sender.isOn + self?.component.isRequired = sender.isOn } optionsSwitch.onChange = { [weak self] sender in @@ -84,7 +93,7 @@ class DropdownSelectViewController: BaseViewController { } readonlySwitch.onChange = { [weak self] sender in - self?.component.readOnly = sender.isOn + self?.component.isReadOnly = sender.isOn } transparentBgSwitch.onChange = { [weak self] sender in @@ -119,6 +128,12 @@ class DropdownSelectViewController: BaseViewController { self?.component.errorText = text }.store(in: &subscribers) + widthTextField + .numberPublisher + .sink { [weak self] number in + self?.component.width = number?.cgFloatValue + }.store(in: &subscribers) + tooltipTitleTextField .textPublisher .sink { [weak self] text in @@ -147,10 +162,6 @@ class DropdownSelectViewController: BaseViewController { component.options = moreOptions /// callback to know which option chose - component.onItemSelected = { index, option in - print("selected index: \(index) text: \(option.text) value: \(option.value)") - } - component.onChange = { dropdown in guard let option = dropdown.selectedItem, let index = dropdown.selectId else { print("nothing selected"); return } print("selected index: \(index) text: \(option.text) value: \(option.value)") @@ -158,9 +169,10 @@ class DropdownSelectViewController: BaseViewController { //setup UI disabledSwitch.isOn = !component.isEnabled - requiredSwitch.isOn = component.required + requiredSwitch.isOn = component.isRequired surfacePickerSelectorView.text = component.surface.rawValue labelTextField.text = component.labelText + helperTextPlacementPickerSelectorView.text = component.helperTextPlacement.rawValue helperTextField.text = component.helperText readonlySwitch.isOn = false transparentBgSwitch.isOn = false @@ -176,6 +188,11 @@ class DropdownSelectViewController: BaseViewController { self?.component.surface = item self?.contentTopView.backgroundColor = item.color } + + helperTextPlacementPickerSelectorView.onPickerDidSelect = { [weak self] item in + self?.component.helperTextPlacement = item + } + } func updateTooltip() { diff --git a/VDSSample/ViewControllers/IconViewController.swift b/VDSSample/ViewControllers/IconViewController.swift index c2d4433..88848a9 100644 --- a/VDSSample/ViewControllers/IconViewController.swift +++ b/VDSSample/ViewControllers/IconViewController.swift @@ -13,12 +13,18 @@ import Combine class IconViewController: BaseViewController { - lazy var colorPickerSelectorView = { + lazy var lightColorPickerSelectorView = { PickerSelectorView(title: "", picker: self.picker, items: UIColor.VDSColor.allCases) }() - + + lazy var darkColorPickerSelectorView = { + PickerSelectorView(title: "", + picker: self.picker, + items: UIColor.VDSColor.allCases) + }() + lazy var namePickerSelectorView = { PickerSelectorView(title: "", picker: self.picker, @@ -45,7 +51,8 @@ class IconViewController: BaseViewController { addFormRow(label: "Surface", view: surfacePickerSelectorView) addFormRow(label: "Size", view: sizePickerSelectorView) addFormRow(label: "Custom Size", view: customSizeField) - addFormRow(label: "Color", view: colorPickerSelectorView) + addFormRow(label: "Light Color", view: lightColorPickerSelectorView) + addFormRow(label: "Dark Color", view: darkColorPickerSelectorView) addFormRow(label: "Name", view: namePickerSelectorView) customSizeField @@ -57,14 +64,13 @@ class IconViewController: BaseViewController { func setupModel() { let name = Icon.Name.accessibility - let color = UIColor.VDSColor.paletteBlack - component.color = color.uiColor component.name = name //setup UI surfacePickerSelectorView.text = component.surface.rawValue sizePickerSelectorView.text = component.size.rawValue - colorPickerSelectorView.text = color.rawValue + lightColorPickerSelectorView.text = UIColor.VDSColor.elementsPrimaryOnlight.rawValue + darkColorPickerSelectorView.text = UIColor.VDSColor.elementsPrimaryOndark.rawValue namePickerSelectorView.text = name.rawValue } func setupPicker(){ @@ -78,14 +84,25 @@ class IconViewController: BaseViewController { self?.component.size = item } - colorPickerSelectorView.onPickerDidSelect = { [weak self] item in - self?.component.color = item.uiColor + lightColorPickerSelectorView.onPickerDidSelect = { [weak self] item in + self?.setColorConfiguration() + } + + darkColorPickerSelectorView.onPickerDidSelect = { [weak self] item in + self?.setColorConfiguration() } namePickerSelectorView.onPickerDidSelect = { [weak self] item in self?.component.name = item } } + + func setColorConfiguration() { + let light = lightColorPickerSelectorView.selectedItem.uiColor + let dark = darkColorPickerSelectorView.selectedItem.uiColor + component.colorConfiguration = .init(light, dark) + } + } extension IconViewController: ComponentSampleable { diff --git a/VDSSample/ViewControllers/InputFieldViewController.swift b/VDSSample/ViewControllers/InputFieldViewController.swift index 61d5350..9ca4875 100644 --- a/VDSSample/ViewControllers/InputFieldViewController.swift +++ b/VDSSample/ViewControllers/InputFieldViewController.swift @@ -19,6 +19,12 @@ class InputFieldViewController: BaseViewController { items: InputField.HelperTextPlacement.allCases) }() + lazy var inputTypePickerSelectorView = { + PickerSelectorView(title: "", + picker: self.picker, + items: InputField.FieldType.allCases) + }() + var disabledSwitch = Toggle() var requiredSwitch = Toggle() var labelTextField = TextField() @@ -31,6 +37,52 @@ class InputFieldViewController: BaseViewController { var tooltipTitleTextField = TextField() var tooltipContentTextField = TextField() + //FieldType sections + + //password + var hidePasswordButtonTextField = TextField() + var showPasswordButtonTextField = TextField() + lazy var passwordSection = FormSection().with { + $0.title = "Password Settings" + $0.addFormRow(label: "Hide Button", view: hidePasswordButtonTextField) + $0.addFormRow(label: "Show Button", view: showPasswordButtonTextField) + $0.isHidden = true + } + + //date + lazy var dateFormatPickerSelectorView = { + PickerSelectorView(title: "", + picker: self.picker, + items: InputField.DateFormat.allCases) + }() + + lazy var dateSection = FormSection().with { + $0.title = "Date Settings" + $0.addFormRow(label: "Date Format", view: dateFormatPickerSelectorView) + $0.isHidden = true + } + + //inlineAction + var inlineActionTextField = TextField() + lazy var inlineActionSection = FormSection().with { + $0.title = "inlineAction Settings" + $0.addFormRow(label: "Action Text", view: inlineActionTextField) + $0.isHidden = true + } + + //securityCode + lazy var cardTypePickerSelectorView = { + PickerSelectorView(title: "", + picker: self.picker, + items: InputField.CreditCardType.allCases) + }() + + lazy var securityCodeSection = FormSection().with { + $0.title = "Security Code Settings" + $0.addFormRow(label: "Card Type", view: cardTypePickerSelectorView) + $0.isHidden = true + } + override func viewDidLoad() { super.viewDidLoad() addContentTopView(view: component) @@ -40,22 +92,40 @@ class InputFieldViewController: BaseViewController { override func setupForm(){ super.setupForm() - addFormRow(label: "Disabled", view: disabledSwitch) - addFormRow(label: "Required", view: requiredSwitch) - addFormRow(label: "Surface", view: surfacePickerSelectorView) - addFormRow(label: "Label Text", view: labelTextField) - addFormRow(label: "Helper Text Placement", view: helperTextPlacementPickerSelectorView) - addFormRow(label: "Helper Text", view: helperTextField) - addFormRow(label: "Error", view: showErrorSwitch) - addFormRow(label: "Error Text", view: errorTextField) - addFormRow(label: "Success", view: showSuccessSwitch) - addFormRow(label: "Success Text", view: successTextField) - addFormRow(label: "Width", view: widthTextField) - addFormRow(label: "ToolTip Title", view: tooltipTitleTextField) - addFormRow(label: "ToolTip Content", view: tooltipContentTextField) + + let fieldType = FormSection().with { + $0.title = "Field Type Settings" + $0.addFormRow(label: "Field Type", view: inputTypePickerSelectorView) + } + + let general = FormSection().with { + $0.title = "\n\nGeneral Settings" + } + + general.addFormRow(label: "Disabled", view: disabledSwitch) + general.addFormRow(label: "Required", view: requiredSwitch) + general.addFormRow(label: "Surface", view: surfacePickerSelectorView) + general.addFormRow(label: "Label Text", view: labelTextField) + general.addFormRow(label: "Helper Text Placement", view: helperTextPlacementPickerSelectorView) + general.addFormRow(label: "Helper Text", view: helperTextField) + general.addFormRow(label: "Error", view: showErrorSwitch) + general.addFormRow(label: "Error Text", view: errorTextField) + general.addFormRow(label: "Success", view: showSuccessSwitch) + general.addFormRow(label: "Success Text", view: successTextField) + general.addFormRow(label: "Width", view: widthTextField) + general.addFormRow(label: "ToolTip Title", view: tooltipTitleTextField) + general.addFormRow(label: "ToolTip Content", view: tooltipContentTextField) + + append(section: fieldType) + append(section: passwordSection) + append(section: dateSection) + append(section: inlineActionSection) + append(section: securityCodeSection) + append(section: general) + requiredSwitch.onChange = { [weak self] sender in - self?.component.required = sender.isOn + self?.component.isRequired = sender.isOn } showErrorSwitch.onChange = { [weak self] sender in @@ -114,17 +184,42 @@ class InputFieldViewController: BaseViewController { self?.updateTooltip() }.store(in: &subscribers) + //field types + //password + hidePasswordButtonTextField + .textPublisher + .sink { [weak self] text in + self?.component.hidePasswordButtonText = text + }.store(in: &subscribers) + + showPasswordButtonTextField + .textPublisher + .sink { [weak self] text in + self?.component.showPasswordButtonText = text + }.store(in: &subscribers) + + //inlineAction + inlineActionTextField + .textPublisher + .sink { [weak self] text in + if !text.isEmpty { + self?.component.actionTextLinkModel = .init(text: text, onClick: { inputField in + var value = inputField.value ?? "" + value = !value.isEmpty ? value : "nil" + self?.present(UIAlertController(title: "inlineAction", message: "Clicked and you get the value: \(value)", preferredStyle: .alert).with{ $0.addAction(.init(title: "OK", style: .default)) }, animated: true) + }) + } else { + self?.component.actionTextLinkModel = nil + } + }.store(in: &subscribers) } func setupModel() { component.fieldType = .text - component.width = 328 - component.text = "Starting Text" component.labelText = "Street Address" component.helperText = "For example: 123 Verizon St" component.errorText = "Enter a valid address." component.successText = "Good job entering a valid address!" - component.tooltipModel = .init(title: "Check the formatting of your address", content:"House/Building number then street name") component.onChange = { component in if let text = component.value { @@ -137,8 +232,10 @@ class InputFieldViewController: BaseViewController { //setup UI surfacePickerSelectorView.text = component.surface.rawValue helperTextPlacementPickerSelectorView.text = component.helperTextPlacement.rawValue + dateFormatPickerSelectorView.text = component.dateFormat.rawValue + inputTypePickerSelectorView.text = component.fieldType.rawValue disabledSwitch.isOn = !component.isEnabled - requiredSwitch.isOn = component.required + requiredSwitch.isOn = component.isRequired labelTextField.text = component.labelText helperTextField.text = component.helperText showErrorSwitch.isOn = component.showError @@ -162,6 +259,21 @@ class InputFieldViewController: BaseViewController { helperTextPlacementPickerSelectorView.onPickerDidSelect = { [weak self] item in self?.component.helperTextPlacement = item } + + inputTypePickerSelectorView.onPickerDidSelect = { [weak self] item in + self?.component.fieldType = item + self?.component.text = "" + self?.updateFormSections() + } + + dateFormatPickerSelectorView.onPickerDidSelect = { [weak self] item in + self?.component.dateFormat = item + self?.updateFormSections() + } + + cardTypePickerSelectorView.onPickerDidSelect = { [weak self] item in + self?.component.cardType = item + } } func updateTooltip() { @@ -171,6 +283,35 @@ class InputFieldViewController: BaseViewController { component.tooltipModel = !title.isEmpty || !content.isEmpty ? .init(title: title, content: content) : nil } + + func updateFormSections() { + [passwordSection, dateSection, inlineActionSection, securityCodeSection].forEach { $0.isHidden = true } + //reset other fields + component.actionTextLinkModel = nil + component.tooltipModel = nil + component.cardType = .generic + tooltipTitleTextField.text = nil + tooltipContentTextField.text = nil + dateFormatPickerSelectorView.text = component.dateFormat.rawValue + cardTypePickerSelectorView.text = component.cardType.rawValue + switch component.fieldType { + case .inlineAction: + inlineActionTextField.text = nil + inlineActionSection.isHidden = false + + case .password: + passwordSection.isHidden = false + + case .date: + dateSection.isHidden = false + + case .securityCode: + securityCodeSection.isHidden = false + + default: + break + } + } } diff --git a/VDSSample/ViewControllers/MenuViewController.swift b/VDSSample/ViewControllers/MenuViewController.swift index fd1f3eb..03069cc 100644 --- a/VDSSample/ViewControllers/MenuViewController.swift +++ b/VDSSample/ViewControllers/MenuViewController.swift @@ -74,13 +74,15 @@ class MenuViewController: UITableViewController, TooltipLaunchable { MenuComponent(title: "Button", completed: true, viewController: ButtonViewController.self), MenuComponent(title: "ButtonGroup", completed: true, viewController: ButtonGroupViewController.self), MenuComponent(title: "ButtonIcon", completed: true, viewController: ButtonIconViewController.self), + MenuComponent(title: "Calendar", completed: true, viewController: CalendarViewController.self), MenuComponent(title: "Carousel Scrollbar", completed: true, viewController: CarouselScrollbarViewConttroller.self), MenuComponent(title: "Checkbox", completed: true, viewController: CheckboxViewController.self), MenuComponent(title: "CheckboxItem", completed: true, viewController: CheckboxItemViewController.self), MenuComponent(title: "CheckboxGroup", completed: true, viewController: CheckboxGroupViewController.self), + MenuComponent(title: "DatePicker", completed: true, viewController: DatePickerViewController.self), MenuComponent(title: "DropdownSelect", completed: true, viewController: DropdownSelectViewController.self), MenuComponent(title: "Icon", completed: true, viewController: IconViewController.self), - MenuComponent(title: "InputField", completed: false, viewController: InputFieldViewController.self), + MenuComponent(title: "InputField", completed: true, viewController: InputFieldViewController.self), MenuComponent(title: "Label", completed: true, viewController: LabelViewController.self), MenuComponent(title: "Line", completed: true, viewController: LineViewController.self), MenuComponent(title: "Loader", completed: true, viewController: LoaderViewController.self), diff --git a/VDSSample/ViewControllers/TableViewTestController.swift b/VDSSample/ViewControllers/TableViewTestController.swift index b7b1ddd..8de4507 100644 --- a/VDSSample/ViewControllers/TableViewTestController.swift +++ b/VDSSample/ViewControllers/TableViewTestController.swift @@ -172,30 +172,8 @@ public class TableViewTestController: UIViewController, Initable, Surfaceable { } var items: [MenuComponent] { - all - } - - var all: [MenuComponent] { MenuViewController.items - } - - var batch1: [MenuComponent] { - [ - MenuComponent(title: "Badge", completed: true, viewController: BadgeViewController.self), - MenuComponent(title: "Button", completed: true, viewController: ButtonViewController.self), - MenuComponent(title: "ButtonGroup", completed: true, viewController: ButtonGroupViewController.self), - MenuComponent(title: "Icon", completed: true, viewController: IconViewController.self), - MenuComponent(title: "Label", completed: true, viewController: LabelViewController.self), - MenuComponent(title: "Line", completed: true, viewController: LineViewController.self), - MenuComponent(title: "Loader", completed: true, viewController: LoaderViewController.self), - MenuComponent(title: "Tabs", completed: true, viewController: TabsViewController.self), - MenuComponent(title: "TextLink", completed: true, viewController: TextLinkViewController.self), - MenuComponent(title: "TextLinkCaret", completed: true, viewController: TextLinkCaretViewController.self), - MenuComponent(title: "TitleLockup", completed: true, viewController: TitleLockupViewController.self), - MenuComponent(title: "Tooltip", completed: true, viewController: TooltipViewController.self), - MenuComponent(title: "TrailingTooltip", completed: true, viewController: TrailingTooltipLabelViewController.self), - ] - } + } } extension TableViewTestController : UITableViewDelegate, UITableViewDataSource { diff --git a/VDSSample/ViewControllers/TextAreaViewController.swift b/VDSSample/ViewControllers/TextAreaViewController.swift index 9769795..3a7b17d 100644 --- a/VDSSample/ViewControllers/TextAreaViewController.swift +++ b/VDSSample/ViewControllers/TextAreaViewController.swift @@ -34,7 +34,6 @@ class TextAreaViewController: BaseViewController