-
-
Notifications
You must be signed in to change notification settings - Fork 197
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(components): add RichText component (#875)
* Add RichText component * Use more efficient traversal * Fix traversal name * Clarify naming * Add DSL for RichText * Create DSL module * Include DSL module in RichText * Remove DSLType * Move smoothing to RichTextView * Remove unnecessary font change * Keep DSL in own module * Revert "Keep DSL in own module" This reverts commit 17e5445. Co-authored-by: Glenn Slotte <glenn@slotte.net>
- Loading branch information
Showing
7 changed files
with
287 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
open Revery; | ||
open Revery.UI; | ||
open Revery.UI.Components; | ||
open Revery.Font; | ||
|
||
let containerStyle = | ||
Style.[ | ||
position(`Absolute), | ||
top(0), | ||
bottom(0), | ||
left(0), | ||
right(0), | ||
alignItems(`Center), | ||
justifyContent(`Center), | ||
flexDirection(`Column), | ||
]; | ||
|
||
module SampleRichText = { | ||
let make = () => { | ||
let richtext = | ||
RichText.( | ||
text("Hello ", ~color=Colors.red, ~fontWeight=Weight.Bold) | ||
++ text("world", ~color=Colors.green) | ||
++ text("!", ~color=Colors.yellow) | ||
|> fontSize(20.) | ||
|> italicized | ||
); | ||
|
||
let dimensions = RichText.measure(richtext); | ||
let widthText = "Width: " ++ string_of_int(dimensions.width); | ||
let heightText = "Height: " ++ string_of_int(dimensions.height); | ||
|
||
<View style=containerStyle> | ||
<RichTextView richtext /> | ||
<Text text=widthText /> | ||
<Text text=heightText /> | ||
</View>; | ||
}; | ||
}; | ||
let render = () => <SampleRichText />; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
open Revery_Core; | ||
open Revery_Font; | ||
|
||
type textInfo = { | ||
fontFamily: Family.t, | ||
fontWeight: Weight.t, | ||
italicized: bool, | ||
monospaced: bool, | ||
fontSize: float, | ||
text: string, | ||
color: Color.t, | ||
}; | ||
type t = | ||
| Leaf(textInfo) | ||
| Node(t, t); | ||
|
||
let (++) = (left: t, right: t) => Node(left, right); | ||
|
||
let rec foldRight = | ||
(fn: ('acc, textInfo) => 'acc, accumulator: 'acc, richtext: t) => | ||
switch (richtext) { | ||
| Leaf(textInfo) => fn(accumulator, textInfo) | ||
| Node(left, right) => | ||
let rightAcc = foldRight(fn, accumulator, right); | ||
let leftAcc = foldRight(fn, rightAcc, left); | ||
leftAcc; | ||
}; | ||
|
||
let rec map = (updateLeaf: textInfo => t, richtext: t) => | ||
switch (richtext) { | ||
| Leaf(textInfo) => updateLeaf(textInfo) | ||
| Node(left, right) => | ||
let newLeft = map(updateLeaf, left); | ||
let newRight = map(updateLeaf, right); | ||
Node(newLeft, newRight); | ||
}; | ||
|
||
let measure = (~smoothing=Smoothing.default, richtext: t) => | ||
foldRight( | ||
(acc: Dimensions.t, textInfo) => { | ||
let dimensions = | ||
Revery_Draw.Text.measure( | ||
~smoothing, | ||
~fontFamily= | ||
Family.toPath( | ||
textInfo.fontFamily, | ||
textInfo.fontWeight, | ||
textInfo.italicized, | ||
textInfo.monospaced, | ||
), | ||
~fontSize=textInfo.fontSize, | ||
textInfo.text, | ||
); | ||
let width = acc.width + int_of_float(dimensions.width); | ||
let height = max(acc.height, int_of_float(dimensions.height)); | ||
|
||
Dimensions.create(~top=0, ~left=0, ~width, ~height, ()); | ||
}, | ||
Dimensions.create(~top=0, ~left=0, ~width=0, ~height=0, ()), | ||
richtext, | ||
); | ||
|
||
module DSL = { | ||
module Defaults = { | ||
let fontFamily = Family.default; | ||
let fontWeight = Weight.Normal; | ||
let italicized = false; | ||
let monospaced = false; | ||
let fontSize = 14.; | ||
let color = Colors.black; | ||
}; | ||
let text = | ||
( | ||
~fontFamily=Defaults.fontFamily, | ||
~fontWeight=Defaults.fontWeight, | ||
~italicized=Defaults.italicized, | ||
~monospaced=Defaults.monospaced, | ||
~fontSize=Defaults.fontSize, | ||
~color=Defaults.color, | ||
text: string, | ||
) => | ||
Leaf({ | ||
fontFamily, | ||
fontWeight, | ||
italicized, | ||
monospaced, | ||
fontSize, | ||
text, | ||
color, | ||
}); | ||
|
||
let fontWeight = (fontWeight: Weight.t, richtext: t) => | ||
richtext |> map(textInfo => Leaf({...textInfo, fontWeight})); | ||
let thin = (richtext: t) => | ||
richtext |> map(textInfo => Leaf({...textInfo, fontWeight: Weight.Thin})); | ||
let ultralight = (richtext: t) => | ||
richtext | ||
|> map(textInfo => Leaf({...textInfo, fontWeight: Weight.UltraLight})); | ||
let light = (richtext: t) => | ||
richtext |> map(textInfo => Leaf({...textInfo, fontWeight: Weight.Light})); | ||
let normal = (richtext: t) => | ||
richtext | ||
|> map(textInfo => Leaf({...textInfo, fontWeight: Weight.Normal})); | ||
let medium = (richtext: t) => | ||
richtext | ||
|> map(textInfo => Leaf({...textInfo, fontWeight: Weight.Medium})); | ||
let semibold = (richtext: t) => | ||
richtext | ||
|> map(textInfo => Leaf({...textInfo, fontWeight: Weight.SemiBold})); | ||
let bold = (richtext: t) => | ||
richtext |> map(textInfo => Leaf({...textInfo, fontWeight: Weight.Bold})); | ||
let ultrabold = (richtext: t) => | ||
richtext | ||
|> map(textInfo => Leaf({...textInfo, fontWeight: Weight.UltraBold})); | ||
let heavy = (richtext: t) => | ||
richtext |> map(textInfo => Leaf({...textInfo, fontWeight: Weight.Heavy})); | ||
|
||
let fontFamily = (fontFamily: Family.t, richtext: t) => | ||
richtext |> map(textInfo => Leaf({...textInfo, fontFamily})); | ||
let italicized = (richtext: t) => | ||
richtext |> map(textInfo => Leaf({...textInfo, italicized: true})); | ||
let monospaced = (richtext: t) => | ||
richtext |> map(textInfo => Leaf({...textInfo, monospaced: true})); | ||
let fontSize = (fontSize: float, richtext: t) => | ||
richtext |> map(textInfo => Leaf({...textInfo, fontSize})); | ||
let color = (color: Color.t, richtext: t) => | ||
richtext |> map(textInfo => Leaf({...textInfo, color})); | ||
}; | ||
include DSL; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
open Revery_Core; | ||
open Revery_Font; | ||
|
||
type textInfo = { | ||
fontFamily: Family.t, | ||
fontWeight: Weight.t, | ||
italicized: bool, | ||
monospaced: bool, | ||
fontSize: float, | ||
text: string, | ||
color: Color.t, | ||
}; | ||
type t = | ||
| Leaf(textInfo) | ||
| Node(t, t); | ||
|
||
let (++): (t, t) => t; | ||
|
||
let foldRight: (('acc, textInfo) => 'acc, 'acc, t) => 'acc; | ||
|
||
let map: (textInfo => t, t) => t; | ||
|
||
let measure: (~smoothing: Smoothing.t=?, t) => Dimensions.t; | ||
|
||
module DSL: { | ||
let text: | ||
( | ||
~fontFamily: Family.t=?, | ||
~fontWeight: Weight.t=?, | ||
~italicized: bool=?, | ||
~monospaced: bool=?, | ||
~fontSize: float=?, | ||
~color: Color.t=?, | ||
string | ||
) => | ||
t; | ||
let fontWeight: (Weight.t, t) => t; | ||
let thin: t => t; | ||
let ultralight: t => t; | ||
let light: t => t; | ||
let normal: t => t; | ||
let medium: t => t; | ||
let semibold: t => t; | ||
let bold: t => t; | ||
let ultrabold: t => t; | ||
let heavy: t => t; | ||
|
||
let fontFamily: (Family.t, t) => t; | ||
let italicized: t => t; | ||
let monospaced: t => t; | ||
let fontSize: (float, t) => t; | ||
let color: (Color.t, t) => t; | ||
}; | ||
let text: | ||
( | ||
~fontFamily: Family.t=?, | ||
~fontWeight: Weight.t=?, | ||
~italicized: bool=?, | ||
~monospaced: bool=?, | ||
~fontSize: float=?, | ||
~color: Color.t=?, | ||
string | ||
) => | ||
t; | ||
let fontWeight: (Weight.t, t) => t; | ||
let thin: t => t; | ||
let ultralight: t => t; | ||
let light: t => t; | ||
let normal: t => t; | ||
let medium: t => t; | ||
let semibold: t => t; | ||
let bold: t => t; | ||
let ultrabold: t => t; | ||
let heavy: t => t; | ||
|
||
let fontFamily: (Family.t, t) => t; | ||
let italicized: t => t; | ||
let monospaced: t => t; | ||
let fontSize: (float, t) => t; | ||
let color: (Color.t, t) => t; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
open Revery_UI; | ||
open Revery_UI_Primitives; | ||
open Revery_Font; | ||
|
||
let make = | ||
(~style=[], ~smoothing=Smoothing.default, ~richtext: RichText.t, ()) => { | ||
let text = | ||
RichText.foldRight( | ||
(acc, textInfo) => | ||
[ | ||
<Text | ||
style=Style.[color(textInfo.color)] | ||
fontFamily={textInfo.fontFamily} | ||
fontWeight={textInfo.fontWeight} | ||
italicized={textInfo.italicized} | ||
monospaced={textInfo.monospaced} | ||
fontSize={textInfo.fontSize} | ||
text={textInfo.text} | ||
smoothing | ||
/>, | ||
...acc, | ||
], | ||
[], | ||
richtext, | ||
); | ||
|
||
// TODO: Add alignItems(`Baseline) if that exists | ||
<View style=Style.[flexDirection(`Row), ...style]> | ||
{text |> React.listToElement} | ||
</View>; | ||
}; |