open ReasonReact; module PrintSection = { [@bs.module "@highpoint/ui-elements"] external reactClass: reactClass = "PrintSection"; let make = children => wrapJsForReason(~reactClass, ~props=Js.Obj.empty(), children); }; module Scrollbar = { [@bs.module "@highpoint/ui-elements"] external reactClass: reactClass = "Scrollbar"; [@bs.deriving abstract] type jsProps = { [@bs.optional] className: string, }; let make = (~className=?, children) => wrapJsForReason(~reactClass, ~props=jsProps(~className?, ()), children); }; module GradeColor = { [@bs.module "@highpoint/ui-elements"] external gradeColor: ReasonReact.reactClass = "GradeColor"; [@bs.deriving abstract] type jsProps = { gradePoints: float, includeInGPA: bool, }; let make = (~gradePoints, ~includeInGPA=true, children) => ReasonReact.wrapJsForReason( ~reactClass=gradeColor, ~props=jsProps(~gradePoints, ~includeInGPA), children, ); }; module Notification = { [@bs.module "@highpoint/ui-elements"] external reactClass: reactClass = "Notification"; open Js.Nullable; let make = ( ~icon, ~title, ~message, ~onClose=?, ~cancelText=?, ~confirmText=?, ~classes=?, ~onConfirm=?, ~onCancel=?, ~timeout=?, children, ) => wrapJsForReason( ~reactClass, ~props={ "icon": icon, "title": title, "message": message, "onClose": onClose->fromOption, "cancelText": cancelText->fromOption, "confirmText": confirmText->fromOption, "classes": classes->fromOption, "onConfirm": onConfirm->fromOption, "onCancel": onCancel->fromOption, "timeout": timeout->fromOption, }, children, ); }; module ModalNotification = { [@bs.deriving jsConverter] type variant = [ | `success | `failure]; [@bs.module "@highpoint/ui-elements"] external reactClass: reactClass = "ModalNotification"; open Js.Nullable; let make = (~icon, ~message, ~open_, ~onClose, ~variant=?, children) => wrapJsForReason( ~reactClass, ~props={ "icon": icon, "message": message, "open": open_, "onClose": onClose, "variant": variant->Belt.Option.map(variantToJs)->fromOption, }, children, ); }; module DatePicker = { [@bs.module "@highpoint/ui-elements"] external reactClass: reactClass = "DatePicker"; let make = ( ~label, ~required=?, ~onChange, ~minDate=?, ~maxDate=?, ~value=?, ~fullWidth=?, ~onlyCalendar=true, ~format=?, ~bordered=?, ~clearable=true, children, ) => wrapJsForReason( ~reactClass, ~props={ "onChange": date => onChange(date->Js.Nullable.toOption), "onlyCalendar": onlyCalendar, "label": label, "value": value->Belt.Option.isNone ? Js.Nullable.null : value->Js.Nullable.fromOption, "minDate": Js.Nullable.fromOption(minDate), "maxDate": Js.Nullable.fromOption(maxDate), "required": Js.Nullable.fromOption(required), "fullWidth": Js.Nullable.fromOption(fullWidth), "format": Js.Nullable.fromOption(format), "bordered": Js.Nullable.fromOption(bordered), "clearable": clearable, }, children, ); }; type backWrapperProps = { label: string, url: string, }; module BackWrapper = { [@bs.module "@highpoint/ui-elements"] external reactClass: reactClass = "BackWrapper"; let make = children => wrapJsForReason(~reactClass, ~props=Js.Obj.empty(), props => children({label: props##label, url: props##url}) ); }; module BackButton = { [@bs.module "@highpoint/ui-elements"] external reactClass: reactClass = "BackButton"; let make = (~render=?, children) => wrapJsForReason(~reactClass, ~props=Js.Obj.empty(), props => switch (render) { | Some(render) => render(props##label) | None => children } ); }; module Clickable = { [@bs.deriving abstract] type jsProps = { onClick: ReactEvent.Mouse.t => unit, [@bs.optional] className: string, [@bs.optional] role: string, [@bs.optional] tabIndex: int, [@bs.optional] tag: string, [@bs.optional] title: string, }; [@bs.module "@highpoint/ui-elements"] external reactClass: reactClass = "Clickable"; let make = ( ~onClick, ~className=?, ~role=?, ~tabIndex=?, ~tag=?, ~title=?, children, ) => wrapJsForReason( ~reactClass, ~props= jsProps( ~onClick, ~className?, ~role?, ~tabIndex?, ~tag?, ~title?, (), ), children, ); }; module InMobileWrapper = { [@bs.deriving abstract] type jsProps = { [@bs.optional] inHybrid: unit => unit, [@bs.optional] inMobile: unit => unit, [@bs.optional] inCX: unit => unit, }; [@bs.module "@highpoint/ui-elements"] external reactClass: reactClass = "InMobileWrapper"; let make = (~inHybrid=?, ~inMobile=?, ~inCX=?, children) => wrapJsForReason( ~reactClass, ~props=jsProps(~inHybrid?, ~inMobile?, ~inCX?, ()), children, ); }; module InAppWrapper = { [@bs.deriving abstract] type jsProps = { [@bs.optional] inHybrid: unit => unit, [@bs.optional] inMobile: unit => unit, [@bs.optional] inCampusExperience: unit => unit, }; [@bs.module "@highpoint/ui-elements"] external reactClass: reactClass = "InAppWrapper"; let make = (~inHybrid=?, ~inMobile=?, ~inCampusExperience=?, children) => wrapJsForReason( ~reactClass, ~props=jsProps(~inHybrid?, ~inMobile?, ~inCampusExperience?, ()), children, ); }; module NewWindow = { [@bs.deriving abstract] type jsProps = { [@bs.optional] className: string, }; [@bs.module "@highpoint/ui-elements"] external reactClass: reactClass = "NewWindow"; let make = (~className=?, children) => wrapJsForReason(~reactClass, ~props=jsProps(~className?, ()), children); }; module OnEscapeListener = { [@bs.deriving abstract] type jsProps = {onEscape: ReactEvent.Keyboard.t}; [@bs.module "@highpoint/ui-elements"] external reactClass: reactClass = "OnEscapeListener"; let make = (~onEscape, children) => wrapJsForReason(~reactClass, ~props=jsProps(~onEscape), children); }; module OnNetworkChange = { [@bs.deriving abstract] type jsProps = {onNetworkChange: bool => unit}; [@bs.module "@highpoint/ui-elements"] external reactClass: reactClass = "OnNetworkChange"; let make = (~onNetworkChange, children) => wrapJsForReason(~reactClass, ~props=jsProps(~onNetworkChange), children); }; module ComboBox = { [@bs.module "@highpoint/ui-elements"] external myJSReactClass: ReasonReact.reactClass = "ComboBox"; let make = ( ~label: string, ~screenReaderLabel: option(string)=?, ~value: string, ~onChange, ~options: option(array((string, string)))=?, ~getOptionLabel: option(array(string) => string)=?, ~renderOption: option(array(string) => reactElement)=?, ~disabled: option(bool)=?, ~required: option(bool)=?, ~showRequired: option(bool)=?, ~displayNoneText: option(string)=?, ~showNoneOption: option(bool)=?, ~className: option(string)=?, ~style: option(ReactDOMRe.Style.t)=?, ~fullWidth: option(bool)=?, ~error: option(bool)=?, ~helperText: option(string)=?, ~inputClass: option(string)=?, ~id: option(string)=?, ~searchable: option(bool)=?, ~noOptionsText: option(string)=?, ~textFieldProps=?, ~disableClearable: option(bool)=?, children, ) => ReasonReact.wrapJsForReason( ~reactClass=myJSReactClass, ~props={ "label": label, "screenReaderLabel": screenReaderLabel->Js.Nullable.fromOption, "value": value, "onChange": onChange, "options": options->Js.Nullable.fromOption, "getOptionLabel": getOptionLabel->Js.Nullable.fromOption, "renderOption": renderOption->Js.Nullable.fromOption, "disabled": disabled->Js.Nullable.fromOption, "required": required->Js.Nullable.fromOption, "showRequired": showRequired->Js.Nullable.fromOption, "displayNoneText": displayNoneText->Js.Nullable.fromOption, "showNoneOption": showNoneOption->Js.Nullable.fromOption, "className": className->Js.Nullable.fromOption, "style": style->Js.Nullable.fromOption, "fullWidth": fullWidth->Js.Nullable.fromOption, "error": error->Js.Nullable.fromOption, "helperText": helperText->Js.Nullable.fromOption, "inputClass": inputClass->Js.Nullable.fromOption, "id": id->Js.Nullable.fromOption, "searchable": searchable->Js.Nullable.fromOption, "noOptionsText": noOptionsText->Js.Nullable.fromOption, "textFieldProps": textFieldProps->Js.Nullable.fromOption, "disableClearable": disableClearable->Js.Nullable.fromOption, }, children, ); }; module MultiSelect = { [@bs.module "@highpoint/ui-elements"] external myJSReactClass: ReasonReact.reactClass = "MultiSelect"; let make = ( ~label, ~screenReaderLabel: option(string)=?, ~value: array(string), ~onChange: array(string) => unit, ~options: option(array((string, string)))=?, ~getOptionLabel: option(array(string) => string)=?, ~renderOption: option(array(string) => reactElement)=?, ~disabled: option(bool)=?, ~required: option(bool)=?, ~showRequired: option(bool)=?, ~showAllOption: bool=false, ~className: option(string)=?, ~style: option(ReactDOMRe.Style.t)=?, ~fullWidth: option(bool)=?, ~error: option(bool)=?, ~helperText: option(string)=?, ~inputClass: option(string)=?, ~id: option(string)=?, ~searchable: option(bool)=?, ~noOptionsText: option(string)=?, ~textFieldProps=?, ~itemToString: option(array(array(string)) => string)=?, ~disableClearable: option(bool)=?, children, ) => ReasonReact.wrapJsForReason( ~reactClass=myJSReactClass, ~props={ "label": label, "screenReaderLabel": screenReaderLabel->Js.Nullable.fromOption, "value": value, "onChange": onChange, "options": options->Js.Nullable.fromOption, "getOptionLabel": getOptionLabel->Js.Nullable.fromOption, "renderOption": renderOption->Js.Nullable.fromOption, "disabled": disabled->Js.Nullable.fromOption, "required": required->Js.Nullable.fromOption, "showRequired": showRequired->Js.Nullable.fromOption, "showAllOption": showAllOption, "className": className->Js.Nullable.fromOption, "style": style->Js.Nullable.fromOption, "fullWidth": fullWidth->Js.Nullable.fromOption, "error": error->Js.Nullable.fromOption, "helperText": helperText->Js.Nullable.fromOption, "inputClass": inputClass->Js.Nullable.fromOption, "id": id->Js.Nullable.fromOption, "searchable": searchable->Js.Nullable.fromOption, "noOptionsText": noOptionsText->Js.Nullable.fromOption, "textFieldProps": textFieldProps->Js.Nullable.fromOption, "itemToString": itemToString->Js.Nullable.fromOption, "disableClearable": disableClearable->Js.Nullable.fromOption, }, children, ); }; module Input = { [@bs.deriving abstract] type jsProps = { label: reactElement, [@bs.optional] name: string, [@bs.optional] onChange: ReactEvent.Form.t => unit, [@bs.optional] checked: bool, [@bs.optional] className: string, [@bs.optional] color: string, [@bs.optional] id: string, [@bs.optional] labelClassName: string, [@bs.optional] title: string, }; module type Config = {let reactClass: reactClass;}; module Make = (Config: Config) => { let make = ( ~label, ~name=?, ~onChange=?, ~checked=?, ~className=?, ~color=?, ~id=?, ~labelClassName=?, ~title=?, children, ) => wrapJsForReason( ~reactClass=Config.reactClass, ~props= jsProps( ~label, ~name?, ~onChange?, ~checked?, ~className?, ~color?, ~id?, ~labelClassName?, ~title?, (), ), children, ); }; }; module Radio = Input.Make({ [@bs.module "@highpoint/ui-elements"] external reactClass: reactClass = "Radio"; }); module Checkbox = Input.Make({ [@bs.module "@highpoint/ui-elements"] external reactClass: reactClass = "Checkbox"; }); module Switch = Input.Make({ [@bs.module "@highpoint/ui-elements"] external reactClass: reactClass = "Switch"; }); module Theme = { module General = { [@bs.deriving abstract] type t = pri { background: string, secondaryBackground: string, line: string, }; }; module Text = { [@bs.deriving abstract] type t = pri { primary: string, primaryDisabled: string, secondary: string, primaryContrast: string, positive: string, negative: string, warning: string, violet: string, sea: string, brown: string, }; }; module Icons = { [@bs.deriving abstract] type t = pri { default: string, positive: string, negative: string, warning: string, pinned: string, friends: string, active: string, }; }; module AdditionalColors = { [@bs.deriving abstract] type t = pri { violetUI: string, seaUI: string, brownUI: string, }; }; [@bs.deriving abstract] type color = pri { primary: string, primaryHover: string, primaryHoverBorder: string, primaryPressed: string, primaryDisabled: string, secondary: string, secondaryHover: string, secondaryDisabled: string, destructive: string, destructiveHover: string, destructiveHoverBorder: string, general: General.t, [@bs.as "text"] textColors: Text.t, icons: Icons.t, additionalColors: AdditionalColors.t, avatars: array(string), }; [@bs.deriving abstract] type fontWeights = pri { light: int, regular: int, text: int, medium: int, semibold: int, }; [@bs.deriving abstract] type font = pri { weights: fontWeights, family: string, }; [@bs.deriving abstract] type classes = { [@bs.as "font"] fontClasses: Js.Dict.t(string), secondaryBorder: string, }; [@bs.deriving abstract] type t = { color, font, classes, }; [@bs.deriving abstract] type theme = pri { [@bs.as "Provider"] provider: reactClass, [@bs.as "Consumer"] consumer: reactClass, }; [@bs.module "@highpoint/ui-elements"] external theme: theme = "Theme"; module Provider = { type config = { . sansSerifFont: string, primaryColor: string, primaryText: string, }; let make = (~config=?, children) => wrapJsForReason( ~reactClass=theme->providerGet, ~props={"config": config->Js.Nullable.fromOption}, children, ); }; module Consumer = { let make = children => wrapJsForReason( ~reactClass=theme->consumerGet, ~props=Js.Obj.empty(), children, ); }; }; module Utilities = { type utilities; [@bs.module "@highpoint/ui-elements"] external utilities: utilities = "Utilities"; module Window = { [@bs.send] external _isFramed: (utilities, unit) => bool = "isFramed"; let isFramed = () => _isFramed(utilities, ()); [@bs.send] external _isInPortal: (utilities, unit) => bool = "isInPortal"; let isInPortal = () => _isInPortal(utilities, ()); [@bs.send] external _isFluidLayout: (utilities, unit) => bool = "isFluidLayout"; let isFluidLayout = () => _isFluidLayout(utilities, ()); }; module Guid = { [@bs.send] external _generateId: (utilities, unit) => string = "generateId"; let generateId = () => _generateId(utilities, ()); }; module Url = { [@bs.send] external _getCrefUrl: (utilities, string) => string = "getCrefUrl"; let getCrefUrl = url => _getCrefUrl(utilities, url); }; module Communication = { [@bs.send] external _on: (utilities, string, unit => unit) => unit = "on"; let on = (message, action) => _on(utilities, message, action); [@bs.send] external _send: (utilities, string) => unit = "send"; let send = message => _send(utilities, message); }; }; module URLWatcher = { open Router; open Js.String; let indexOfEnd = (str, match) => { let index = str->indexOf(match, _); index == (-1) ? (-1) : index + match->length; }; let join = (list, ~separator="/", ()) => list->Belt.List.reduce(_, "", (acc, item) => acc ++ separator ++ item); module type PathInterface = {let psPathEndString: string;}; module Path = (Config: PathInterface) => { let cleanupPathString = stringPath => stringPath ->split("/", _) ->Belt.List.fromArray ->Belt.List.keep(str => str !== ""); let stripActualPath = path => { let stringPath = path->join(); stringPath ->substring( ~from=1, ~to_=stringPath->indexOfEnd(Config.psPathEndString), ) ->cleanupPathString; }; let getActualPath = path => { let stringPath = path->join(); stringPath ->substr(~from=stringPath->indexOfEnd(Config.psPathEndString)) ->cleanupPathString; }; }; let initialUrl = dangerouslyGetInitialUrl(); type url = Router.url; type navigate = (~path: list(string)=?, unit) => unit; type push = list(string) => unit; type watchApi = { url, navigate, push, }; type state = {url}; type action = | Change(url); let component = reducerComponent("URL Watcher"); let make = (~psPathEndString, children) => { ...component, initialState: () => {url: initialUrl}, reducer: (action, _state) => switch (action) { | Change(url) => Update({url: url}) }, didMount: ({send, onUnmount}) => { let watcherID = watchUrl(url => url->Change->send); onUnmount(() => unwatchUrl(watcherID)); }, render: ({state}) => { module Path = Path({ let psPathEndString = psPathEndString; }); let _navigate = (~path=[], ~initialPath=state.url.path, ()) => ( (initialPath @ path) ->Belt.List.reduce("", (acc, item) => acc ++ "/" ++ item) ++ "?" ++ state.url.search ) ->Router.push; let navigate = _navigate(~initialPath=state.url.path->Path.stripActualPath); let push = path => _navigate(~path, ()); let path = state.url.path->Path.getActualPath; let url = {path, hash: state.url.hash, search: state.url.search}; {url, push, navigate}->children; }, }; }; let watchUrl = (~psPathEndString="_Main", children) => ...children ;