From 73fcde9219d6ae273c3027d1eed6ecdb052aaf2a Mon Sep 17 00:00:00 2001 From: Hari Roshan Date: Sun, 21 May 2023 13:16:03 +0530 Subject: [PATCH] Allows adding user defined custom elements (#7) * added null check for el * added customElements field * renamed dashed to kebabCased * refactored and exposed addViewRender and buildHandler * exposed build handler * added types for customElements * increased version * added customElements Class extending ability * minor change version bump * testing custom elements with animated circle * added missing element definition * fixed ns-animated circle issue --- app/app.js | 54 +++++++++++--- app/src/Flick.elm | 81 ++++++++++++++------- elm-native-js/index.d.ts | 56 ++++++++++++++ elm-native-js/package.json | 2 +- elm-native-js/src/App.res | 28 +++++-- elm-native-js/src/Native/Constants.res | 76 +++++++++---------- elm-native-js/src/Native/Elements.res | 38 +++++----- elm-native-js/src/Native/Elements.resi | 6 ++ elm-native-js/src/Native/Layouts.resi | 1 + elm-native-js/types/Native/Elements.bs.d.ts | 2 + package.json | 1 + yarn.lock | 13 +++- 12 files changed, 257 insertions(+), 101 deletions(-) diff --git a/app/app.js b/app/app.js index 61cb0d2..9fe0a0b 100644 --- a/app/app.js +++ b/app/app.js @@ -1,22 +1,52 @@ -import Elm from "./src/Details.elm"; +import Elm from "./src/Flick.elm"; import { start } from "../elm-native-js" -import { knownFolders, path, ImageSource } from '@nativescript/core' -import * as imagePicker from '@nativescript/imagepicker' +import { AnimatedCircle } from "@nativescript/animated-circle"; +import { kebabCased, view } from "../elm-native-js/src/Native/Constants.bs" +import { buildHandler, addViewRender } from "../elm-native-js/src/Native/Elements.bs" -function getImageTempFolder() { - return knownFolders.temp().getFolder("nsimagepicker") -} +// import { knownFolders, path, ImageSource } from '@nativescript/core' +// import * as imagePicker from '@nativescript/imagepicker' -function clearImageTempFolder() { - getImageTempFolder().clear() -} +// function getImageTempFolder() { +// return knownFolders.temp().getFolder("nsimagepicker") +// } + +// function clearImageTempFolder() { +// getImageTempFolder().clear() +// } + +const animatedCircleAttributes = + ["backgroundColor", + "width", + "height", + "animated", + "animateFrom", + "rimColor", + "barColor", + "fillColor", + "clockwise", + "rimWidth", + "progress", + "text", + "textSize", + "textColor"].map(kebabCased) start( { elmModule: Elm, - elmModuleName: "Details", - initPorts: elmPorts => { + elmModuleName: "Flick", + customElements: [ + { + tagName: 'ns-animated-circle', + handler: buildHandler( + () => new AnimatedCircle(), + view.concat(animatedCircleAttributes), + addViewRender + ) + } + ] + /* initPorts: elmPorts => { elmPorts.pickImage.subscribe(_ => { // Clear the temp foler clearImageTempFolder() @@ -47,7 +77,7 @@ start( .catch((errorMessage) => console.log(errorMessage)) }) - } + } */ } ) /* diff --git a/app/src/Flick.elm b/app/src/Flick.elm index e2286e7..25088f1 100644 --- a/app/src/Flick.elm +++ b/app/src/Flick.elm @@ -1,6 +1,8 @@ module Flick exposing (main) import Browser +import Html exposing (node) +import Html.Attributes exposing (attribute) import Json.Decode as D import Json.Encode as E import Native exposing (Native) @@ -75,6 +77,7 @@ main = type NavPage = HomePage | DetailsPage + | AnimatedCircle type alias Model = @@ -96,7 +99,7 @@ encodeFlix flick = init : ( Model, Cmd Msg ) init = - ( { rootFrame = Frame.init HomePage + ( { rootFrame = Frame.init AnimatedCircle , picked = Nothing , flick = Native.makeListViewModel encodeFlix response @@ -155,33 +158,33 @@ update msg model = {- - Layout.asElement <| - Layout.flexboxLayout - [ NA.flexDirection "column" - ] - [ Native.listPicker - [ E.list E.string - [ "2022", "2021", "2020" ] - |> NA.items - , NA.selectedIndex "1" - ] - [] + Layout.asElement <| + Layout.flexboxLayout + [ NA.flexDirection "column" + ] + [ Native.listPicker + [ E.list E.string + [ "2022", "2021", "2020" ] + |> NA.items + , NA.selectedIndex "1" ] + [] + ] - Native.listView - [ E.list E.int [ 2022, 2021, 2020, 2019, 2018, 2017 ] |> NA.items - , NA.itemTemplateSelector "{{ $value % 2 == 0 ? 'even' : 'odd' }}" - ] - [ Layout.asElement <| - Layout.stackLayout - [ NA.key "even" ] - [ Native.label [ NA.text "{{ $value.toString() }}", NA.color "green" ] [] - ] - , Layout.asElement <| - Layout.stackLayout - [ NA.key "odd" ] - [ Native.label [ NA.text "{{ $value.toString() }}", NA.color "red" ] [] ] - ] + Native.listView + [ E.list E.int [ 2022, 2021, 2020, 2019, 2018, 2017 ] |> NA.items + , NA.itemTemplateSelector "{{ $value % 2 == 0 ? 'even' : 'odd' }}" + ] + [ Layout.asElement <| + Layout.stackLayout + [ NA.key "even" ] + [ Native.label [ NA.text "{{ $value.toString() }}", NA.color "green" ] [] + ] + , Layout.asElement <| + Layout.stackLayout + [ NA.key "odd" ] + [ Native.label [ NA.text "{{ $value.toString() }}", NA.color "red" ] [] ] + ] -} @@ -299,6 +302,29 @@ detailsPage model = ) +animatedCirclePage : Native Msg +animatedCirclePage = + Page.pageWithActionBar Back + [] + (Native.actionBar [ NA.title "Animated Circle" ] []) + (node "ns-animated-circle" + [ attribute "background-color" "transparent" + , attribute "width" "200" + , attribute "height" "200" + , attribute "animated" "true" + , attribute "animate-from" "0" + , attribute "rim-color" "#FF5722" + , attribute "bar-color" "#3D8FF4" + , attribute "fill-color" "#eee" + , attribute "clockwise" "true" + , attribute "rim-width" "5" + , attribute "progress" "50" + , attribute "text" "50%" + , attribute "text-size" "28" + , attribute "text-color" "red" + ] + []) + getPage : Model -> NavPage -> Native Msg getPage model page = case page of @@ -308,6 +334,9 @@ getPage model page = HomePage -> homePage model + AnimatedCircle -> + animatedCirclePage + view : Model -> Native Msg view model = diff --git a/elm-native-js/index.d.ts b/elm-native-js/index.d.ts index b19345f..256af8f 100644 --- a/elm-native-js/index.d.ts +++ b/elm-native-js/index.d.ts @@ -1,9 +1,65 @@ +import * as NativescriptCore from "./types/Native/NativescriptCore.bs"; +declare function render(current: any, param: any): void; + +type htmlElementClass = any +type nativeObject = any type port = any +/* You don't have to build this object from scratch. You can use helper function in + buildHandler in Native/Elements.bs for UI elements + buildHandler in Native/Layouts.bs for Layouts +*/ +type handler = { + /* A function to create Nativescript object */ + init: () => nativeObject; + /* An array of attribute strings in Kebab Case. Use kebabCased function in Native/Constants.bs to convert your camel cased attributes to kebab case + * Don't forget to call prefixWithBind(withTransformedArrayOfStrings) if you want to use the attributes in a bindExpression + */ + observedAttributes: string[]; + update: typeof NativescriptCore.update; + render: any; + handlerKind: number; + dispose: typeof NativescriptCore.dispose; + addEventListener: typeof NativescriptCore.addEventListener; + removeEventListener: typeof NativescriptCore.removeEventListener; +} +type customElement = { + tagName: string, + handler: handler, +} type config = { elmModule: () => any, elmModuleName: string, flags?: any, initPorts?: (ports: port) => void, + /* + Here's how you can define your own customElements and use in elm + import { buildHandler, addViewRender } from "elm-native-js/src/Native/Elements.bs" + import { kebabCased, view } from "elm-native-js/src/Native/Constants.bs" + import SomePlugin from 'some-native-script-plugin' + + ... + const somePluginAttributes = ['attributeToWatch1', 'attributeToWatch2'].map(kebabCased) + // If you want to use it in a bind expression, call prefixWithBind(somePluginAttributes) exported from Native/Constants.bs + + ... + + const config = { + ... + customElements: + [ { tagName: 'ns-some-tag-name', + handler: buildHandler( + () => new SomePlugin(), + view.concat(somePluginAttributes), + addViewRender // For most cases, this is what you need. Refer Native/Elements.bs and Native/Helper.bs for other kinds + ) + } + ] + } + + start(config) + */ + customElements?: customElement[], + extendCustomElements?: (tagName: string, htmlElementClass: htmlElementClass) => htmlElementClass } export function start(config: config): void; diff --git a/elm-native-js/package.json b/elm-native-js/package.json index 7ced40a..fe6f222 100644 --- a/elm-native-js/package.json +++ b/elm-native-js/package.json @@ -1,6 +1,6 @@ { "name": "elm-native-js", - "version": "1.0.3", + "version": "1.1.0", "description": "Nativescript bindings for elm using custom HTML elements", "keywords": ["elm", "elm-native", "nativescript", "elm mobile"], "main": "index.js", diff --git a/elm-native-js/src/App.res b/elm-native-js/src/App.res index f65759f..fa066a9 100644 --- a/elm-native-js/src/App.res +++ b/elm-native-js/src/App.res @@ -12,6 +12,8 @@ type rec context = { isAndroid: bool, taskportInit: unit => unit, initPorts: Js.Nullable.t unit>, + customElements: Js.Nullable.t>, + extendCustomElements: Js.Nullable.t<(. string, Obj.t) => Obj.t>, withCustomElements: (. Obj.t, Types.handler) => Obj.t, elements: array, run: unit => unit, @@ -32,10 +34,22 @@ type rec context = { let initElements = (params: context) => { let htmlElement = params.window->Mock.hTMLElement let customElements = params.window->Mock.customElements - - params.elements->Belt.Array.forEach(element => { + let defineElements = (element: Types.customElement) => { let newClass = params.withCustomElements(. htmlElement, element.handler) - customElements.define(. element.tagName, newClass) + let extendedClass = + params.extendCustomElements + ->Js.Nullable.toOption + ->Belt.Option.mapWithDefault(newClass, (fx: (. string, Obj.t) => Obj.t) => + fx(. element.tagName, newClass) + ) + + customElements.define(. element.tagName, extendedClass) + } + params.elements->Belt.Array.forEach(defineElements) + params.customElements + ->Js.Nullable.toOption + ->Belt.Option.forEach((customElementsArray: array) => { + customElementsArray->Belt.Array.forEach(defineElements) }) } ) @@ -45,6 +59,8 @@ type config = { elmModuleName: string, flags: Js.Nullable.t, initPorts: Js.Nullable.t unit>, + customElements: Js.Nullable.t>, + extendCustomElements: Js.Nullable.t<(. string, Obj.t) => Obj.t>, } let start: config => unit = config => { @@ -61,6 +77,8 @@ let start: config => unit = config => { initElements, flags: config.flags, initPorts: config.initPorts, + customElements: config.customElements, + extendCustomElements: config.extendCustomElements, isIOS: Types.isIOS, isAndroid: Types.isAndroid, elm: config.elmModule, @@ -73,7 +91,7 @@ let start: config => unit = config => { }), } - let defineCustomElements = `initElements({window, withCustomElements, elements})` + let defineCustomElements = `initElements({window, withCustomElements, elements, extendCustomElements, customElements})` let elmRoot = "elm-root" let elmInitScript = ` @@ -82,7 +100,7 @@ let start: config => unit = config => { node: document.getElementById('${elmRoot}'), flags: flags }) - if(initPorts != null) initPorts(el.ports) + if(el != null && initPorts != null) initPorts(el.ports) ` let html = `App
` diff --git a/elm-native-js/src/Native/Constants.res b/elm-native-js/src/Native/Constants.res index 0ae75d8..c8c8701 100644 --- a/elm-native-js/src/Native/Constants.res +++ b/elm-native-js/src/Native/Constants.res @@ -4,7 +4,7 @@ let camelCased: string => string = %raw(` } `) -let dashed: string => string = %raw(` +let kebabCased: string => string = %raw(` function(str) { return str.replace(/[A-Z]/g, m => "-" + m.toLowerCase()); } @@ -130,12 +130,12 @@ let view: array = "width", "key", ] - ->Belt.Array.map(dashed) + ->Belt.Array.map(kebabCased) ->prefixWithBind let paddings: array = ["padding", "paddingBottom", "paddingLeft", "paddingRight", "paddingTop"] - ->Belt.Array.map(dashed) + ->Belt.Array.map(kebabCased) ->prefixWithBind ->prefixWithBind @@ -143,7 +143,7 @@ let layoutBase: array = [ view, paddings, - ["clipToBounds", "isPassThroughParentEnabled"]->Belt.Array.map(dashed)->prefixWithBind, + ["clipToBounds", "isPassThroughParentEnabled"]->Belt.Array.map(kebabCased)->prefixWithBind, ]->Belt.Array.concatMany let textBase: array = @@ -166,34 +166,34 @@ let textBase: array = "whiteSpace", "textWrap", ] - ->Belt.Array.map(dashed) + ->Belt.Array.map(kebabCased) ->prefixWithBind, ]->Belt.Array.concatMany let dockLayout: array = - [layoutBase, ["stretchLastChild"]->Belt.Array.map(dashed)->prefixWithBind]->Belt.Array.concatMany + [layoutBase, ["stretchLastChild"]->Belt.Array.map(kebabCased)->prefixWithBind]->Belt.Array.concatMany let gridLayout: array = - [layoutBase, ["columns", "rows"]->Belt.Array.map(dashed)->prefixWithBind]->Belt.Array.concatMany + [layoutBase, ["columns", "rows"]->Belt.Array.map(kebabCased)->prefixWithBind]->Belt.Array.concatMany let stackLayout: array = - [layoutBase, ["orientation"]->Belt.Array.map(dashed)->prefixWithBind]->Belt.Array.concatMany + [layoutBase, ["orientation"]->Belt.Array.map(kebabCased)->prefixWithBind]->Belt.Array.concatMany let wrapLayout: array = [ stackLayout, - ["itemHeight", "itemWidth"]->Belt.Array.map(dashed)->prefixWithBind, + ["itemHeight", "itemWidth"]->Belt.Array.map(kebabCased)->prefixWithBind, ]->Belt.Array.concatMany let flexboxLayout: array = [ layoutBase, ["alignContent", "alignItems", "flexDirection", "flexWrap", "justifyContent"] - ->Belt.Array.map(dashed) + ->Belt.Array.map(kebabCased) ->prefixWithBind, ]->Belt.Array.concatMany -let button = [textBase, ["textWrap"]->Belt.Array.map(dashed)->prefixWithBind]->Belt.Array.concatMany +let button = [textBase, ["textWrap"]->Belt.Array.map(kebabCased)->prefixWithBind]->Belt.Array.concatMany let frameBase = [ @@ -205,7 +205,7 @@ let frameBase = "defaultAnimatedNavigation", "defaultTransition", ] - ->Belt.Array.map(dashed) + ->Belt.Array.map(kebabCased) ->prefixWithBind, ]->Belt.Array.concatMany @@ -220,32 +220,32 @@ let pageBase = "enableSwipeBackNavigation", "statusBarStyle", ] - ->Belt.Array.map(dashed) + ->Belt.Array.map(kebabCased) ->prefixWithBind, ]->Belt.Array.concatMany let activityIndicator = - [view, ["busy"]->Belt.Array.map(dashed)->prefixWithBind]->Belt.Array.concatMany + [view, ["busy"]->Belt.Array.map(kebabCased)->prefixWithBind]->Belt.Array.concatMany /* for simplicity using view instead of viewBase */ let formattedString = [ view, - ["fontStyle", "style", "fontFamily", "fontWeight"]->Belt.Array.map(dashed)->prefixWithBind, + ["fontStyle", "style", "fontFamily", "fontWeight"]->Belt.Array.map(kebabCased)->prefixWithBind, ]->Belt.Array.concatMany let span = - [formattedString, ["text"]->Belt.Array.map(dashed)->prefixWithBind]->Belt.Array.concatMany + [formattedString, ["text"]->Belt.Array.map(kebabCased)->prefixWithBind]->Belt.Array.concatMany let datePicker = [ view, ["date", "day", "iosPreferredDatePickerStyle", "maxDate", "minDate", "month", "year"] - ->Belt.Array.map(dashed) + ->Belt.Array.map(kebabCased) ->prefixWithBind, ]->Belt.Array.concatMany -let htmlView = [view, ["html"]->Belt.Array.map(dashed)->prefixWithBind]->Belt.Array.concatMany +let htmlView = [view, ["html"]->Belt.Array.map(kebabCased)->prefixWithBind]->Belt.Array.concatMany let image = [ @@ -260,15 +260,15 @@ let image = "stretch", "tintColor", ] - ->Belt.Array.map(dashed) + ->Belt.Array.map(kebabCased) ->prefixWithBind, ]->Belt.Array.concatMany let listPicker = - [view, ["selectedIndex"]->Belt.Array.map(dashed)->prefixWithBind]->Belt.Array.concatMany + [view, ["selectedIndex"]->Belt.Array.map(kebabCased)->prefixWithBind]->Belt.Array.concatMany let progress = - [view, ["maxValue", "value"]->Belt.Array.map(dashed)->prefixWithBind]->Belt.Array.concatMany + [view, ["maxValue", "value"]->Belt.Array.map(kebabCased)->prefixWithBind]->Belt.Array.concatMany let scrollView = [ @@ -282,7 +282,7 @@ let scrollView = "scrollableWidth", "verticalOffset", ] - ->Belt.Array.map(dashed) + ->Belt.Array.map(kebabCased) ->prefixWithBind, ]->Belt.Array.concatMany @@ -290,27 +290,27 @@ let searchBar = [ view, ["hint", "text", "textFieldBackgroundColor", "textFieldHintColor"] - ->Belt.Array.map(dashed) + ->Belt.Array.map(kebabCased) ->prefixWithBind, ]->Belt.Array.concatMany let segmentedBarItem = - [view, ["title"]->Belt.Array.map(dashed)->prefixWithBind]->Belt.Array.concatMany + [view, ["title"]->Belt.Array.map(kebabCased)->prefixWithBind]->Belt.Array.concatMany let segmentedBar = [ view, - ["selectedBackgroundColor", "selectedIndex"]->Belt.Array.map(dashed)->prefixWithBind, + ["selectedBackgroundColor", "selectedIndex"]->Belt.Array.map(kebabCased)->prefixWithBind, ]->Belt.Array.concatMany let slider = [ view, - ["value", "minValue", "maxValue"]->Belt.Array.map(dashed)->prefixWithBind, + ["value", "minValue", "maxValue"]->Belt.Array.map(kebabCased)->prefixWithBind, ]->Belt.Array.concatMany let switchComponent = - [view, ["checked"]->Belt.Array.map(dashed)->prefixWithBind]->Belt.Array.concatMany + [view, ["checked"]->Belt.Array.map(kebabCased)->prefixWithBind]->Belt.Array.concatMany let tabView = [ @@ -327,14 +327,14 @@ let tabView = "tabTextColor", "tabTextFontSize", ] - ->Belt.Array.map(dashed) + ->Belt.Array.map(kebabCased) ->prefixWithBind, ]->Belt.Array.concatMany let tabViewItem = [ view, - ["canBeLoaded", "iconSource", "textTransform", "title"]->Belt.Array.map(dashed)->prefixWithBind, + ["canBeLoaded", "iconSource", "textTransform", "title"]->Belt.Array.map(kebabCased)->prefixWithBind, ]->Belt.Array.concatMany let commonTextBase = @@ -361,7 +361,7 @@ let commonTextBase = "updateTextTrigger", "whiteSpace", ] - ->Belt.Array.map(dashed) + ->Belt.Array.map(kebabCased) ->prefixWithBind let textField = @@ -369,7 +369,7 @@ let textField = view, paddings, commonTextBase, - ["closeOnReturn", "secure", "secureWithoutAutofill"]->Belt.Array.map(dashed)->prefixWithBind, + ["closeOnReturn", "secure", "secureWithoutAutofill"]->Belt.Array.map(kebabCased)->prefixWithBind, ]->Belt.Array.concatMany let textView = @@ -377,7 +377,7 @@ let textView = view, paddings, commonTextBase, - ["maxLines"]->Belt.Array.map(dashed)->prefixWithBind, + ["maxLines"]->Belt.Array.map(kebabCased)->prefixWithBind, ]->Belt.Array.concatMany let timePicker = @@ -394,24 +394,24 @@ let timePicker = "minuteInterval", "time", ] - ->Belt.Array.map(dashed) + ->Belt.Array.map(kebabCased) ->prefixWithBind, ]->Belt.Array.concatMany let webView = [ view, - ["canGoBack", "canGoForward", "src"]->Belt.Array.map(dashed)->prefixWithBind, + ["canGoBack", "canGoForward", "src"]->Belt.Array.map(kebabCased)->prefixWithBind, ]->Belt.Array.concatMany let actionBar = - [view, ["title", "flat"]->Belt.Array.map(dashed)->prefixWithBind]->Belt.Array.concatMany + [view, ["title", "flat"]->Belt.Array.map(kebabCased)->prefixWithBind]->Belt.Array.concatMany let actionItem = [ view, ["text", "icon", "ios.position", "android.position", "ios.systemIcon", "android.systemIcon"] - ->Belt.Array.map(dashed) + ->Belt.Array.map(kebabCased) ->prefixWithBind, ]->Belt.Array.concatMany @@ -421,13 +421,13 @@ let listView = [ view, ["itemTemplateSelector", "iosEstimatedRowHeight", "rowHeight", "separatorColor"] - ->Belt.Array.map(dashed) + ->Belt.Array.map(kebabCased) ->prefixWithBind, ]->Belt.Array.concatMany // Js.log("****************************") // ["iosEstimatedRowHeight", "rowHeight", "separatorColor"] -// ->Belt.Array.map(dashed) +// ->Belt.Array.map(kebabCased) // ->Belt.Array.forEach(prop => // Js.log( // ` diff --git a/elm-native-js/src/Native/Elements.res b/elm-native-js/src/Native/Elements.res index b2a5c84..56bb6fb 100644 --- a/elm-native-js/src/Native/Elements.res +++ b/elm-native-js/src/Native/Elements.res @@ -18,6 +18,8 @@ let buildHandler: ( removeEventListener: NativescriptCore.removeEventListener, } +let addViewRender: Js.Nullable.t<(. Types.htmlElement, Types.nativeObject) => unit> = makeRender(Helper.addView) + module Label = { %%private( @module("@nativescript/core") @new @@ -25,7 +27,7 @@ module Label = { ) let tagName = "ns-label" - let handler: Types.handler = buildHandler(new, Constants.textBase, makeRender(Helper.addView)) + let handler: Types.handler = buildHandler(new, Constants.textBase, addViewRender) } module Button = { @@ -35,7 +37,7 @@ module Button = { ) let tagName = "ns-button" - let handler: Types.handler = buildHandler(new, Constants.button, makeRender(Helper.addView)) + let handler: Types.handler = buildHandler(new, Constants.button, addViewRender) } module Placeholder = { @@ -45,7 +47,7 @@ module Placeholder = { ) let tagName = "ns-placeholder" - let handler: Types.handler = buildHandler(new, Constants.view, makeRender(Helper.addView)) + let handler: Types.handler = buildHandler(new, Constants.view, addViewRender) } module ActionBar = { @@ -99,7 +101,7 @@ module ActivityIndicator = { let handler: Types.handler = buildHandler( new, Constants.activityIndicator, - makeRender(Helper.addView), + addViewRender, ) } @@ -132,7 +134,7 @@ module DatePicker = { ) let tagName = "ns-datepicker" - let handler: Types.handler = buildHandler(new, Constants.datePicker, makeRender(Helper.addView)) + let handler: Types.handler = buildHandler(new, Constants.datePicker, addViewRender) } module HtmlView = { %%private( @@ -141,7 +143,7 @@ module HtmlView = { ) let tagName = "ns-html-view" - let handler: Types.handler = buildHandler(new, Constants.htmlView, makeRender(Helper.addView)) + let handler: Types.handler = buildHandler(new, Constants.htmlView, addViewRender) } module Image = { %%private( @@ -150,7 +152,7 @@ module Image = { ) let tagName = "ns-image" - let handler: Types.handler = buildHandler(new, Constants.image, makeRender(Helper.addView)) + let handler: Types.handler = buildHandler(new, Constants.image, addViewRender) } module Progress = { @@ -160,7 +162,7 @@ module Progress = { ) let tagName = "ns-progress" - let handler: Types.handler = buildHandler(new, Constants.progress, makeRender(Helper.addView)) + let handler: Types.handler = buildHandler(new, Constants.progress, addViewRender) } module ListPicker = { %%private( @@ -189,7 +191,7 @@ module ScrollView = { ) let tagName = "ns-scroll-view" - let handler: Types.handler = buildHandler(new, Constants.scrollView, makeRender(Helper.addView)) + let handler: Types.handler = buildHandler(new, Constants.scrollView, addViewRender) } module SearchBar = { @@ -199,7 +201,7 @@ module SearchBar = { ) let tagName = "ns-search-bar" - let handler: Types.handler = buildHandler(new, Constants.searchBar, makeRender(Helper.addView)) + let handler: Types.handler = buildHandler(new, Constants.searchBar, addViewRender) } module SegmentedBar = { @@ -209,7 +211,7 @@ module SegmentedBar = { ) let tagName = "ns-segmented-bar" - let handler: Types.handler = buildHandler(new, Constants.segmentedBar, makeRender(Helper.addView)) + let handler: Types.handler = buildHandler(new, Constants.segmentedBar, addViewRender) } module SegmentedBarItem = { @@ -233,7 +235,7 @@ module Slider = { ) let tagName = "ns-slider" - let handler: Types.handler = buildHandler(new, Constants.slider, makeRender(Helper.addView)) + let handler: Types.handler = buildHandler(new, Constants.slider, addViewRender) } module Switch = { @@ -246,7 +248,7 @@ module Switch = { let handler: Types.handler = buildHandler( new, Constants.switchComponent, - makeRender(Helper.addView), + addViewRender, ) } @@ -257,7 +259,7 @@ module TabView = { ) let tagName = "ns-tab-view" - let handler: Types.handler = buildHandler(new, Constants.tabView, makeRender(Helper.addView)) + let handler: Types.handler = buildHandler(new, Constants.tabView, addViewRender) } module TabViewItem = { @@ -289,7 +291,7 @@ module TextField = { ) let tagName = "ns-textfield" - let handler: Types.handler = buildHandler(new, Constants.textField, makeRender(Helper.addView)) + let handler: Types.handler = buildHandler(new, Constants.textField, addViewRender) } module TextView = { @@ -299,7 +301,7 @@ module TextView = { ) let tagName = "ns-text-view" - let handler: Types.handler = buildHandler(new, Constants.textView, makeRender(Helper.addView)) + let handler: Types.handler = buildHandler(new, Constants.textView, addViewRender) } module TimePicker = { @@ -309,7 +311,7 @@ module TimePicker = { ) let tagName = "ns-time-picker" - let handler: Types.handler = buildHandler(new, Constants.timePicker, makeRender(Helper.addView)) + let handler: Types.handler = buildHandler(new, Constants.timePicker, addViewRender) } module WebView = { @@ -319,7 +321,7 @@ module WebView = { ) let tagName = "ns-web-view" - let handler: Types.handler = buildHandler(new, Constants.webView, makeRender(Helper.addView)) + let handler: Types.handler = buildHandler(new, Constants.webView, addViewRender) } module ListView = { %%private( diff --git a/elm-native-js/src/Native/Elements.resi b/elm-native-js/src/Native/Elements.resi index 7168393..99f677c 100644 --- a/elm-native-js/src/Native/Elements.resi +++ b/elm-native-js/src/Native/Elements.resi @@ -1 +1,7 @@ let all: array +let addViewRender: Js.Nullable.t<(. Types.htmlElement, Types.nativeObject) => unit> +let buildHandler: ( + unit => Types.nativeObject, + array, + Js.Nullable.t<(. Types.htmlElement, Types.nativeObject) => unit>, +) => Types.handler diff --git a/elm-native-js/src/Native/Layouts.resi b/elm-native-js/src/Native/Layouts.resi index 7168393..e043b5d 100644 --- a/elm-native-js/src/Native/Layouts.resi +++ b/elm-native-js/src/Native/Layouts.resi @@ -1 +1,2 @@ let all: array +let buildHandler: (unit => Types.nativeObject, array) => Types.handler diff --git a/elm-native-js/types/Native/Elements.bs.d.ts b/elm-native-js/types/Native/Elements.bs.d.ts index ba7a266..15b9d2f 100644 --- a/elm-native-js/types/Native/Elements.bs.d.ts +++ b/elm-native-js/types/Native/Elements.bs.d.ts @@ -12,3 +12,5 @@ export var all: { }; }[]; import * as NativescriptCore from "./NativescriptCore.bs.js"; + +export function buildHandler(newFunction: () => any, observedAttributes: string[], render) : void diff --git a/package.json b/package.json index f2142cb..f032c3f 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "build:webpack": "webpack --mode development" }, "dependencies": { + "@nativescript/animated-circle": "^1.1.7", "@nativescript/core": "~8.4.0", "@nativescript/imagepicker": "^1.0.9", "@nativescript/theme": "~3.0.2", diff --git a/yarn.lock b/yarn.lock index 6c40be5..d1c9291 100644 --- a/yarn.lock +++ b/yarn.lock @@ -243,6 +243,11 @@ "@jridgewell/resolve-uri" "3.1.0" "@jridgewell/sourcemap-codec" "1.4.14" +"@nativescript/animated-circle@^1.1.7": + version "1.1.7" + resolved "https://registry.yarnpkg.com/@nativescript/animated-circle/-/animated-circle-1.1.7.tgz#3421c9ec6c21b16c53e4a171c12e843bf0f3c563" + integrity sha512-TTU1vLjBDiV+yNUtCYkN8GDFLqib661ZwGJh04cQlwQ356dJ+J7AEWFQDx14xD1GtBSOKY3aCLglaCGNWZhzmw== + "@nativescript/core@~8.4.0": version "8.4.3" resolved "https://registry.npmjs.org/@nativescript/core/-/core-8.4.3.tgz" @@ -1191,12 +1196,18 @@ electron-to-chromium@^1.4.251: integrity sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA== elm-native-js@./elm-native-js: - version "0.1.0" + version "1.1.0" dependencies: + elm-taskport "^2.0.1" happy-dom "^6.0.4" rescript "^10.0.1" vm-shim "^0.0.6" +elm-taskport@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/elm-taskport/-/elm-taskport-2.0.1.tgz#abaf091db79971b8354ddc2652c6c0c7abd91b5b" + integrity sha512-8UgIjzmGuoU6Wt6VC0tkJnzvc5xHL5yH7GdN+/QNxaaA3ckoyveCtV0QJqNCRa42bpyR1JhOwLSApwf2Id5xZg== + elm-webpack-loader@^8.0.0: version "8.0.0" resolved "https://registry.npmjs.org/elm-webpack-loader/-/elm-webpack-loader-8.0.0.tgz"