123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168(** Contain utilities for CSS containment. *)moduleCss=Cascade.CssmoduleHandler=structopenStyleopenCsstypet=|None|Strict|Content|Size|Layout|Paint|Contain_style|Inline_size|Arbitraryofstringletname="contain"letpriority_=34(* Single source of truth: (handler, class_suffix, suborder) for
non-arbitrary. Composable utilities (inline-size, layout, paint, size,
style) come first alphabetically, then arbitrary, then simple ones
(content, none, strict) alphabetically. *)letcontain_data=[(Inline_size,"inline-size",0);(Layout,"layout",1);(Paint,"paint",2);(Size,"size",3);(Contain_style,"style",4);(Content,"content",6);(None,"none",7);(Strict,"strict",8);]letsuborder=function|Arbitrary_->5|t->(matchList.assoc_optt(List.map(fun(t,_,o)->(t,o))contain_data)with|Someo->o|None->100)letto_class=function|Arbitrarys->"contain-["^s^"]"|t->(matchList.assoc_optt(List.map(fun(t,s,_)->(t,s))contain_data)with|Somesuffix->"contain-"^suffix|None->"contain-none")(* Channel variables for composable contain — these generate @property rules
and initial-value declarations in the properties layer. property_order
groups them together; they use syntax: "*" with no initial-value. *)lettw_contain_size_var=Var.channel~needs_property:true~property_order:50Css.Value"tw-contain-size"lettw_contain_layout_var=Var.channel~needs_property:true~property_order:50Css.Value"tw-contain-layout"lettw_contain_paint_var=Var.channel~needs_property:true~property_order:50Css.Value"tw-contain-paint"lettw_contain_style_var=Var.channel~needs_property:true~property_order:50Css.Value"tw-contain-style"letall_contain_vars=[tw_contain_size_var;tw_contain_layout_var;tw_contain_paint_var;tw_contain_style_var;]letcontain_property_rules=List.filter_mapVar.property_ruleall_contain_vars|>concat(* The composable contain value using all four variables with empty fallbacks.
This allows combining multiple contain utilities - each sets its variable,
and the contain property references all of them. *)letcomposable_contain_value=letvvar:Css.contain=Css.Var(Var.bracket~fallback:Css.Empty(Var.namevar))inCss.List[vtw_contain_size_var;vtw_contain_layout_var;vtw_contain_paint_var;vtw_contain_style_var;](* Create a composable contain style that sets one variable *)letcomposable_containvarset_value=letdecl=Var.setvar(Css.Variables.custom_value_identset_value)instyle~property_rules:contain_property_rules[decl;containcomposable_contain_value]letto_style_theme=function|None->style[containCss.None]|Strict->style[containCss.Strict]|Content->style[containCss.Content]|Size->composable_containtw_contain_size_var"size"|Inline_size->composable_containtw_contain_size_var"inline-size"|Layout->composable_containtw_contain_layout_var"layout"|Paint->composable_containtw_contain_paint_var"paint"|Contain_style->composable_containtw_contain_style_var"style"|Arbitrarys->((* Parse the arbitrary value *)matchString.lowercase_asciiswith|"none"->style[containCss.None]|"strict"->style[containCss.Strict]|"content"->style[containCss.Content]|"size"->style[containCss.Size]|"layout"->style[containCss.Layout]|"style"->style[containCss.Style]|"paint"->style[containCss.Paint]|"inline-size"->style[containCss.Inline_size]|"inherit"->style[containCss.Inherit]|"initial"->style[containCss.Initial]|"unset"->style[containCss.Unset]|"revert"->style[containCss.Revert]|"revert-layer"->style[containCss.Revert_layer]|_->(* Unknown arbitrary value — wrap as bare var ref *)style[contain(Css.Var(Var.brackets))])letof_class_map=List.map(fun(t,s,_)->("contain-"^s,t))contain_dataletof_class_themeclass_name=matchList.assoc_optclass_nameof_class_mapwith|Somet->Okt|None->(* Check for arbitrary value: contain-[value] *)ifString.starts_with~prefix:"contain-["class_namethenletlen=String.lengthclass_nameinifclass_name.[len-1]=']'thenOk(Arbitrary(String.subclass_name9(len-10)))elseError(`Msg"Invalid contain arbitrary value")elseError(`Msg"Not a contain utility")letexamples=[Strict]endmoduleUtility_factory=Utility.Make(Handler)letutility=Utility_factory.v(* Convenience functions *)letcontain_none=utilityHandler.Noneletcontain_strict=utilityHandler.Strictletcontain_content=utilityHandler.Contentletcontain_size=utilityHandler.Sizeletcontain_layout=utilityHandler.Layoutletcontain_paint=utilityHandler.Paintletcontain_style=utilityHandler.Contain_styleletcontain_inline_size=utilityHandler.Inline_sizeletcontain_arbitrarys=utility(Handler.Arbitrarys)