@@ -669,304 +669,157 @@ type alias Text msg =
669669 }
670670
671671
672−type Padding
673− = Padding Int Int Int Int
674−
675−
676−inheritablePlaceholderAttributes attr =
677− case attr of
678− Internal.StyleClass _ (Internal.PaddingStyle _ _ _ _ _) ->
679− True
680−
681− Internal.StyleClass _ (Internal.BorderWidth _ _ _ _ _) ->
682− True
683−
684− Internal.StyleClass _ (Internal.Transform _) ->
685− True
686−
687− _ ->
688− False
689−
690−
691−{-|
692−
693− attributes
694−
695− <parent>
696− attribute::width/height fill
697− attribtue::alignment
698− attribute::spacing
699− attribute::fontsize/family/lineheight
700− <el-wrapper>
701− attribute::nearby(placeholder)
702− attribute::width/height fill
703− inFront ->
704− placeholder
705− attribute::padding
706−
707−
708− <input>
709− textarea ->
710− special height for height-content
711− attribtue::padding
712− attribute::lineHeight
713− attributes
714− <label>
715−
716−-}
672+{-| -}
717673textHelper : TextInput -> List (Attribute msg) -> Text msg -> Element msg
718674textHelper textInput attrs textOptions =
719675 let
720− attributes =
676+ withDefaults =
721677 defaultTextBoxStyle ++ attrs
722678
723− behavior =
724− [ Internal.Attr (Html.Events.onInput textOptions.onChange) ]
679+ redistributed =
680+ redistribute withDefaults
725681
726− forPlaceholder =
727− List.filter inheritablePlaceholderAttributes attributes
682+ moveUpToCompensateForPadding =
683+ calcMoveToCompensateForPadding withDefaults
728684
729− noNearbys =
730− List.filter (not << forNearby) attributes
731−
732− forNearby attr =
685+ onlySpacing attr =
733686 case attr of
734− Internal.Nearby _ _ ->
687+ Internal.StyleClass _ (Internal.SpacingStyle _ _ _) ->
735688 True
736689
737690 _ ->
738691 False
739692
740− ( inputNode, inputAttrs, inputChildren ) =
741− case textInput.type_ of
742− TextInputNode inputType ->
743− ( "input"
744− , [ Internal.Attr (Html.Attributes.type_ inputType)
745− , value textOptions.text
746− , spellcheck textInput.spellchecked
747− , Internal.htmlClass classes.inputText
748− , case textInput.autofill of
749− Nothing ->
750− Internal.NoAttribute
751−
752− Just fill ->
753− autofill fill
754− ]
755− ++ noNearbys
756− , []
757− )
758−
759− TextArea ->
760− let
761− { maybePadding, heightContent, maybeSpacing, adjustedAttributes, maybeBorder } =
762− (value textOptions.text :: attributes)
763− |> List.foldr
764− (\attr found ->
765− case attr of
766− Internal.Describe _ ->
767− found
768−
769− Internal.Height len ->
770− case found.heightContent of
771− Nothing ->
772− { found
773− | heightContent = Just (Internal.isContent len)
774− , adjustedAttributes = attr :: found.adjustedAttributes
775− }
776−
777− _ ->
778− found
779−
780− Internal.StyleClass _ (Internal.BorderWidth _ t r b l) ->
781− case found.maybeBorder of
782− Nothing ->
783− { found
784− | maybeBorder = Just (Padding t r b l)
785− , adjustedAttributes = attr :: found.adjustedAttributes
786− }
787−
788− _ ->
789− found
790−
791− Internal.StyleClass _ (Internal.PaddingStyle _ t r b l) ->
792− case found.maybePadding of
793− Nothing ->
794− { found
795− | maybePadding = Just (Padding t r b l)
796−
797− -- Skip storing padding because it's being customized later
798− , adjustedAttributes = found.adjustedAttributes
799− }
800−
801− _ ->
802− found
803−
804− Internal.StyleClass _ (Internal.SpacingStyle _ x y) ->
805− case found.maybeSpacing of
806− Nothing ->
807− { found
808− | maybeSpacing = Just y
809− , adjustedAttributes = attr :: found.adjustedAttributes
810− }
811−
812− _ ->
813− found
814−
815− _ ->
816− { found | adjustedAttributes = attr :: found.adjustedAttributes }
817− )
818− { maybePadding = Nothing
819− , heightContent = Nothing
820− , maybeBorder = Nothing
821− , maybeSpacing = Nothing
822− , adjustedAttributes = []
823− }
824−
825− -- NOTE: This is where default text spacing is set
826− spacing =
827− Maybe.withDefault 5 maybeSpacing
828− in
829− ( "textarea"
830− , [ spellcheck textInput.spellchecked
831− , Internal.htmlClass classes.inputMultiline
832− , Maybe.map autofill textInput.autofill
833− |> Maybe.withDefault Internal.NoAttribute
834− , case maybePadding of
835− Nothing ->
836− Internal.NoAttribute
837−
838− Just (Padding t r b l) ->
839− Element.paddingEach
840− { top = max 0 (t - (spacing // 2))
841− , bottom = max 0 (b - (spacing // 2))
842− , left = l
843− , right = r
844− }
845− , case heightContent of
846− Nothing ->
847− Internal.NoAttribute
848−
849− Just True ->
850− textHeightContent textOptions.text spacing maybePadding maybeBorder
851−
852− Just False ->
853− Internal.NoAttribute
854− ]
855− ++ adjustedAttributes
856− , []
857− )
858−
859− heightFillFromChild =
860− Internal.get attributes <|
861− \attr ->
862− case attr of
863− Internal.Height (Internal.Fill _) ->
864− True
865−
866− _ ->
867− False
868−
869− attributesFromChild =
870− Internal.get attributes <|
871− \attr ->
872− case attr of
873− Internal.Width (Internal.Fill _) ->
874− True
875−
876− Internal.Height (Internal.Fill _) ->
877− True
878−
879− Internal.AlignX _ ->
880− True
881−
882− Internal.AlignY _ ->
883− True
884−
885− Internal.StyleClass _ (Internal.SpacingStyle _ _ _) ->
886− True
887−
888− Internal.StyleClass _ (Internal.FontSize _) ->
889− True
890−
891− Internal.StyleClass _ (Internal.FontFamily _ _) ->
892− True
693+ isHeightContent attr =
694+ case attr of
695+ Internal.Height Internal.Content ->
696+ True
893697
894− _ ->
895− False
698+ _ ->
699+ False
896700
897− nearbys =
898− Internal.get attributes <|
899− \attr ->
900− case attr of
901− Internal.Nearby _ _ ->
902− True
701+ bottomPadding attr =
702+ case attr of
703+ Internal.StyleClass cls (Internal.PaddingStyle pad t r b l) ->
704+ Just <|
705+ Element.paddingEach
706+ { top = 0
707+ , right = 0
708+ , bottom = b
709+ , left = 0
710+ }
903711
904− _ ->
905− False
712+ _ ->
713+ Nothing
906714
907− inputPadding =
908− Internal.get attributes <|
909− \attr ->
910− case attr of
911− Internal.StyleClass _ (Internal.PaddingStyle _ _ _ _ _) ->
912− True
715+ heightContent =
716+ case textInput.type_ of
717+ TextInputNode inputType ->
718+ False
913719
914− _ ->
915− False
720+ TextArea ->
721+ List.any isHeightContent withDefaults
916722
917723 inputElement =
918724 Internal.element
919725 Internal.asEl
920− Internal.div
921− (Element.width Element.fill
922− :: List.concat
923− [ nearbys
924− , heightFillFromChild
925− , case textOptions.placeholder of
926− Nothing ->
927− []
928−
929− Just (Placeholder placeholderAttrs placeholderEl) ->
930− [ Element.inFront
931− (Element.el
932− (defaultTextPadding
933− :: forPlaceholder
934− ++ [ Font.color charcoal
935− , Internal.htmlClass (classes.noTextSelection ++ " " ++ classes.passPointerEvents)
936− , Border.color (Element.rgba 0 0 0 0)
937− , Background.color (Element.rgba 0 0 0 0)
938− , Element.height Element.fill
939− , Element.width Element.fill
940− , Element.alpha
941− (if textOptions.text == "" then
942− 1
943−
944− else
945− 0
946− )
947− ]
948− ++ placeholderAttrs
949− )
950− placeholderEl
951− )
726+ (case textInput.type_ of
727+ TextInputNode inputType ->
728+ Internal.NodeName "input"
729+
730+ TextArea ->
731+ Internal.NodeName "textarea"
732+ )
733+ ([ value textOptions.text
734+ , Internal.Attr (Html.Events.onInput textOptions.onChange)
735+ , hiddenLabelAttribute textOptions.label
736+ , spellcheck textInput.spellchecked
737+ , Maybe.map autofill textInput.autofill
738+ |> Maybe.withDefault Internal.NoAttribute
739+ ]
740+ ++ (case textInput.type_ of
741+ TextInputNode inputType ->
742+ [ Internal.Attr (Html.Attributes.type_ inputType)
743+ , Internal.htmlClass classes.inputText
744+ , Internal.htmlClass "focusable"
745+ ]
746+
747+ TextArea ->
748+ [ Element.clip
749+ , Element.height Element.fill
750+ , Internal.htmlClass classes.inputMultiline
751+ , Element.alpha 0.3
752+ , moveUpToCompensateForPadding
952753 ]
953− ]
754+ )
755+ ++ redistributed.input
954756 )
955− (Internal.Unkeyed
956− [ Internal.element
757+ (Internal.Unkeyed [])
758+
759+ wrappedInput =
760+ -- if heightContent then
761+ case textInput.type_ of
762+ TextArea ->
763+ -- textarea with height-content means that
764+ -- the input element is rendered `inFront` and transparently.
765+ -- Then the input text is rendered as the actual element.
766+ Internal.element
957767 Internal.asEl
958− (Internal.NodeName inputNode)
959− (List.concat
960− [ [ focusDefault attrs
961− , hiddenLabelAttribute textOptions.label
962− ]
963− , inputAttrs
964− , behavior
768+ Internal.div
769+ ([ Element.width Element.fill
770+ , Element.height (Element.px 100)
771+ , Element.scrollbarY
772+ , Internal.htmlClass classes.focusedWithin
773+ ]
774+ ++ redistributed.parent
775+ )
776+ (Internal.Unkeyed
777+ [ Internal.element
778+ Internal.asParagraph
779+ Internal.div
780+ (Element.width Element.fill
781+ :: Element.height Element.fill
782+ :: Element.inFront inputElement
783+ :: Internal.htmlClass classes.inputMultiline
784+ :: List.concat
785+ [ if heightContent then
786+ redistributed.wrapper
787+
788+ else
789+ redistributed.wrapper
790+ ++ List.filterMap bottomPadding redistributed.parent
791+ , case textOptions.placeholder of
792+ Nothing ->
793+ []
794+
795+ Just place ->
796+ [ renderPlaceholder place redistributed.cover (textOptions.text == "")
797+ ]
798+ ]
799+ )
800+ (Internal.Unkeyed
801+ [ Internal.unstyled (Html.text textOptions.text) ]
802+ )
965803 ]
966804 )
967− (Internal.Unkeyed inputChildren)
968− ]
969− )
805+
806+ TextInputNode inputType ->
807+ Internal.element
808+ Internal.asEl
809+ Internal.div
810+ (Element.width Element.fill
811+ :: List.concat
812+ [ redistributed.parent
813+ , case textOptions.placeholder of
814+ Nothing ->
815+ []
816+
817+ Just place ->
818+ [ renderPlaceholder place redistributed.cover (textOptions.text == "")
819+ ]
820+ ]
821+ )
822+ (Internal.Unkeyed [ inputElement ])
970823 in
971824 applyLabel
972825 (Internal.Class Flag.cursor classes.cursorText
@@ -978,45 +831,207 @@ textHelper textInput attrs textOptions =
978831 5
979832 )
980833 :: Region.announce
981− :: attributesFromChild
834+ :: redistributed.fullParent
982835 )
983836 textOptions.label
984− inputElement
837+ wrappedInput
838+
839+
840+renderPlaceholder (Placeholder placeholderAttrs placeholderEl) forPlaceholder on =
841+ Element.inFront
842+ (Element.el
843+ (defaultTextPadding
844+ :: forPlaceholder
845+ ++ [ Font.color charcoal
846+ , Internal.htmlClass (classes.noTextSelection ++ " " ++ classes.passPointerEvents)
847+ , Border.color (Element.rgba 0 0 0 0)
848+ , Background.color (Element.rgba 0 0 0 0)
849+ , Element.height Element.fill
850+ , Element.width Element.fill
851+ , Element.alpha
852+ (if on then
853+ 1
854+
855+ else
856+ 0
857+ )
858+ ]
859+ ++ placeholderAttrs
860+ )
861+ placeholderEl
862+ )
985863
986864
987−textHeightContent textValue spacing maybePadding maybeBorder =
865+{-| Because textareas are now shadowed, where they're rendered twice,
866+we to move the literal text area up because spacing is based on line height.
867+-}
868+calcMoveToCompensateForPadding : List (Attribute msg) -> Attribute msg
869+calcMoveToCompensateForPadding attrs =
988870 let
989− newlineCount =
990− String.lines textValue
991− |> List.length
992− |> (\x ->
993− if x < 1 then
994− 1
871+ gatherSpacing attr found =
872+ case attr of
873+ Internal.StyleClass _ (Internal.SpacingStyle _ x y) ->
874+ case found of
875+ Nothing ->
876+ Just y
995877
996− else
997− x
998− )
878+ _ ->
879+ found
999880
1000− topBottom (Padding t _ b _) =
1001− t + b
881+ _ ->
882+ found
883+ in
884+ case List.foldr gatherSpacing Nothing attrs of
885+ Nothing ->
886+ Internal.NoAttribute
1002887
1003− additionalSpacing =
1004− ((newlineCount - 1) * spacing)
1005− + Maybe.withDefault 0 (Maybe.map topBottom maybePadding)
1006− + Maybe.withDefault 0 (Maybe.map topBottom maybeBorder)
888+ Just vSpace ->
889+ Element.moveUp (toFloat vSpace / 2)
1007890
1008− heightValue count =
1009− "calc("
1010− ++ String.fromInt count
1011− ++ "em + "
1012− ++ String.fromInt additionalSpacing
1013− ++ "px) !important"
1014− in
1015− Internal.StyleClass Flag.heightTextAreaContent
1016− (Internal.Single ("textarea-height-" ++ String.fromInt newlineCount)
1017− "height"
1018− (heightValue newlineCount)
1019− )
891+
892+{-| Given the list of attributes provided to `Input.multiline` or `Input.text`,
893+
894+redistribute them to the parent, the input, or the cover.
895+
896+ - fullParent -> Wrapper around label and input
897+ - parent -> parent of wrapper
898+ - wrapper -> the element that is here to take up space.
899+ - cover -> things like placeholders or text areas which are layered on top of input.
900+ - input -> actual input element
901+
902+-}
903+redistribute :
904+ List (Attribute msg)
905+ ->
906+ { fullParent : List (Attribute msg)
907+ , parent : List (Attribute msg)
908+ , wrapper : List (Attribute msg)
909+ , input : List (Attribute msg)
910+ , cover : List (Attribute msg)
911+ }
912+redistribute attrs =
913+ List.foldl redistributeOver
914+ { fullParent = []
915+ , parent = []
916+ , input = []
917+ , cover = []
918+ , wrapper = []
919+ }
920+ attrs
921+ |> (\redist ->
922+ { parent = List.reverse redist.parent
923+ , fullParent = List.reverse redist.fullParent
924+ , wrapper = List.reverse redist.wrapper
925+ , input = List.reverse redist.input
926+ , cover = List.reverse redist.cover
927+ }
928+ )
929+
930+
931+redistributeOver attr els =
932+ case attr of
933+ Internal.Nearby _ _ ->
934+ { els | parent = attr :: els.parent }
935+
936+ Internal.Width (Internal.Fill _) ->
937+ { els | fullParent = attr :: els.fullParent }
938+
939+ Internal.Width _ ->
940+ { els | parent = attr :: els.parent }
941+
942+ Internal.Height (Internal.Fill _) ->
943+ { els
944+ | fullParent = attr :: els.fullParent
945+ , parent = attr :: els.parent
946+ }
947+
948+ Internal.Height h ->
949+ { els
950+ | parent = attr :: els.parent
951+ }
952+
953+ Internal.AlignX _ ->
954+ { els | fullParent = attr :: els.fullParent }
955+
956+ Internal.AlignY _ ->
957+ { els | fullParent = attr :: els.fullParent }
958+
959+ Internal.StyleClass _ (Internal.SpacingStyle _ _ _) ->
960+ { els
961+ | fullParent = attr :: els.fullParent
962+ , parent = attr :: els.parent
963+ , input = attr :: els.input
964+ , wrapper = attr :: els.wrapper
965+ }
966+
967+ Internal.StyleClass _ (Internal.PaddingStyle _ _ _ _ _) ->
968+ { els
969+ | parent = attr :: els.parent
970+
971+ -- input = attr :: els.input
972+ -- , wrapper = attr :: els.wrapper
973+ , cover = attr :: els.cover
974+ }
975+
976+ Internal.StyleClass _ (Internal.BorderWidth _ _ _ _ _) ->
977+ { els
978+ | parent = attr :: els.parent
979+ , cover = attr :: els.cover
980+ }
981+
982+ Internal.StyleClass _ (Internal.Transform _) ->
983+ { els
984+ | parent = attr :: els.parent
985+ , cover = attr :: els.cover
986+ }
987+
988+ Internal.StyleClass _ (Internal.FontSize _) ->
989+ { els | fullParent = attr :: els.fullParent }
990+
991+ Internal.StyleClass _ (Internal.FontFamily _ _) ->
992+ { els | fullParent = attr :: els.fullParent }
993+
994+ Internal.StyleClass _ _ ->
995+ { els | parent = attr :: els.parent }
996+
997+ Internal.NoAttribute ->
998+ els
999+
1000+ Internal.Attr a ->
1001+ { els | input = attr :: els.input }
1002+
1003+ Internal.Describe _ ->
1004+ { els | input = attr :: els.input }
1005+
1006+ Internal.Class _ _ ->
1007+ { els | parent = attr :: els.parent }
1008+
1009+ Internal.TransformComponent _ _ ->
1010+ { els | input = attr :: els.input }
1011+
1012+
1013+orElse thing maybe =
1014+ case maybe of
1015+ Nothing ->
1016+ Just thing
1017+
1018+ _ ->
1019+ maybe
1020+
1021+
1022+inheritablePlaceholderAttributes attr =
1023+ case attr of
1024+ Internal.StyleClass _ (Internal.PaddingStyle _ _ _ _ _) ->
1025+ True
1026+
1027+ Internal.StyleClass _ (Internal.BorderWidth _ _ _ _ _) ->
1028+ True
1029+
1030+ Internal.StyleClass _ (Internal.Transform _) ->
1031+ True
1032+
1033+ _ ->
1034+ False
10201035
10211036
10221037{-| -}