import Elementary /// A decorative inline SVG stroke icon, drawn in the current text colour. struct Icon: HTML { // MARK: Properties /// The glyph the icon draws. let glyph: Glyph /// The icon's rendered width and height, in pixels. let size: Int /// The stroke width, or `nil` for the glyph's own. let weight: String? // MARK: Initializers /// Creates an icon. /// - Parameters: /// - glyph: the glyph the icon draws. /// - size: the icon's rendered width and height, in pixels; 20 by default. /// - weight: the stroke width, or `nil` (the default) for the glyph's own. init( _ glyph: Glyph, size: Int = 20, weight: String? = nil ) { self.glyph = glyph self.size = size self.weight = weight } // MARK: Computed /// Rendered raw: the markup is static, never user input. var body: some HTML { HTMLRaw( """ """ ) } } // MARK: - Enumerations extension Icon { /// A glyph an ``Icon`` can draw. enum Glyph { /// A bell. case bell /// A bookmark. case bookmark /// A check mark. case check /// A cross. case close /// A page of text. case document /// Filter lines. case filter /// A key. case key /// A padlock. case lock /// A speech bubble. case message /// A magnifying glass. case search /// A shopfront. case shop /// Sort arrows. case sort } } extension Icon.Glyph { // MARK: Computed /// The shapes the glyph is drawn with. var shapes: String { switch self { case .bell: #""# case .bookmark: #""# case .check: #""# case .close: #""# case .document: #""# case .filter: #""# case .key: #""# case .lock: #""# case .message: #""# case .search: #""# case .shop: #""# case .sort: #""# } } /// The glyph's stroke width; heavier for glyphs drawn small. var strokeWidth: String { switch self { case .check: "3.5" case .close, .filter, .key, .search, .sort: "2.2" default: "2" } } }