Skip to content

Commit

Permalink
- Issue #91: "Attr.readOnly false" fixed
Browse files Browse the repository at this point in the history
- Removed diagnostic output to console
- Observable.init: Provide the initial value for a sequence so that new subscribers will receive an immediate update of the current value. Probably only useful for IObservables that are not derived from an initial IStore
- IReadOnlyStore.Dispose(f), IStore.Dispose(f) : Call f() when the store is disposed
- Removed dependency on ConstructStyleSheetsPolyfill and included directly
- Fixed some warnings in the App (not part of the nuget pkg)
  • Loading branch information
davedawkins committed Sep 21, 2024
1 parent a5b1426 commit d28700e
Show file tree
Hide file tree
Showing 21 changed files with 4,487 additions and 1,936 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ examples/HelloWorld/package-lock.json
examples/HelloWorld/public/bundle.js
devtools/js/bundle.js
tests/public/test-bundle.js
tests/test/**/*.js
tests/build
.vscode/settings.json
public/apidocs
Expand Down
8 changes: 8 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
### 2.0.14
- Issue #91: "Attr.readOnly false" fixed
- Removed diagnostic output to console
- Observable.init: Provide the initial value for a sequence so that new subscribers will receive an immediate update of the current value. Probably only useful for IObservables that are not derived from an initial IStore
- IReadOnlyStore.Dispose(f), IStore.Dispose(f) : Call f() when the store is disposed
- Removed dependency on ConstructStyleSheetsPolyfill and included directly
- Fixed some warnings in the App (not part of the nuget pkg)

### 2.0.13
- Merged PR #84: Added Observable.map2 and Store.map2 functions (thanks to sajagi)

Expand Down
2 changes: 1 addition & 1 deletion src/App/App.fs
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@ let viewPage (view:System.IObservable<BookPageView>) =
// eliminate this.
| Url url -> Html.a [ Attr.href url; text url ]
with
|x -> Html.div[ text $"Creating example {page.Title}: {x.Message}" ]
|x -> Html.div [ text $"Creating example {page.Title}: {x.Message}" ]
| _ -> viewSource view)
]

Expand Down
2 changes: 1 addition & 1 deletion src/App/App.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,11 @@
<ProjectReference Include="..\Sutil\Sutil.fsproj" />
</ItemGroup>
<ItemGroup>
<!-- <PackageReference Include="FSharp.Core" Version="5.0.2" /> -->
<PackageReference Include="Fable.Formatting.Markdown" Version="1.0.1" />
<PackageReference Include="Feliz.Engine.Bulma" Version="1.*-*" />
<PackageReference Include="Fable.Fetch" Version="2.2.0" />
<PackageReference Include="Fable.ShadowStyles" Version="1.0.0-*" />
<PackageReference Include="Feliz.ReactFlow" Version="0.2.2" />
<PackageReference Include="Fable.SimpleXml" Version="3.*" />
</ItemGroup>
<Target Name="ReallyClean" AfterTargets="Clean">
Expand Down
6 changes: 3 additions & 3 deletions src/App/FileInputs.fs
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@ let view() =
let files = Store.make Unchecked.defaultof<Browser.Types.FileList>
let fileSeq = files |> Store.map (Helpers.fileListToSeq >> Seq.toList)

fileSeq |> (Store.iter (fun fileSeq ->
let unsub = fileSeq |> (Store.iter (fun fileSeq ->
// Note that `files` is of type `FileList`, not an Array:
// https://developer.mozilla.org/en-US/docs/Web/API/FileList
//console.log(files);

for file in fileSeq do
Browser.Dom.console.log($"{file.name}: {file.size} bytes")))
Browser.Dom.console.log($"{file.name}: {file.size} bytes")))

Html.div [
disposeOnUnmount [ files ]
disposeOnUnmount [ files; unsub ]

Html.div [
class' "block"
Expand Down
4 changes: 2 additions & 2 deletions src/App/ReactiveStatements.fs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ let plural n = if n = 1 then "" else "s"
let view() =
let count = Store.make 0

count |> Store.iter (fun n ->
let unsub = count |> Store.iter (fun n ->
if n >= 10 then
window.alert("count is dangerously high!")
count <~ 9
Expand All @@ -25,7 +25,7 @@ let view() =
count <~= inc // or: Store.modify count inc

Html.button [
disposeOnUnmount [count]
disposeOnUnmount [count; unsub ]

onClick handleClick []

Expand Down
7 changes: 7 additions & 0 deletions src/Sutil/ConstructStyleSheetsPolyfill.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module ConstructStyleSheetsPolyfill

open Fable.Core.JsInterop

importSideEffects "./adoptedStyleSheets.js"

let register() = ()
33 changes: 17 additions & 16 deletions src/Sutil/DomHelpers.fs
Original file line number Diff line number Diff line change
Expand Up @@ -405,13 +405,22 @@ module ClassHelpers =

let internal nullToEmpty s = if isNull s then "" else s

let private booleanAttributes =
[ "hidden"
"disabled"
"readonly"
"required"
"checked" ] |> Set

let private isBooleanAttribute (name : string) = booleanAttributes.Contains (name.ToLower())

let private toBool (v : obj) =
if v :? bool then
v :?> bool
else
string v <> "false"

let internal setAttribute (el: HTMLElement) (name: string) (value: obj) =
let isBooleanAttribute name =
(name = "hidden"
|| name = "disabled"
|| name = "readonly"
|| name = "required"
|| name = "checked")

let svalue = string value

Expand All @@ -422,14 +431,9 @@ let internal setAttribute (el: HTMLElement) (name: string) (value: obj) =
el |> ClassHelpers.addToClasslist svalue
else if name = "class-" then
el |> ClassHelpers.removeFromClasslist svalue
else if isBooleanAttribute name then
let bValue =
if value :? bool then
value :?> bool
else
svalue <> "false"
else if isBooleanAttribute (name) then
// we'd call el.toggleAttribute( name, bValue) if it was available
if bValue then
if toBool value then
el.setAttribute (name, "")
else
el.removeAttribute name
Expand All @@ -442,9 +446,6 @@ let internal setAttribute (el: HTMLElement) (name: string) (value: obj) =
else
el.setAttribute (name, svalue)


let private idSelector = sprintf "#%s"
let private classSelector = sprintf ".%s"
let private findElement (doc: Document) selector = doc.querySelector (selector)

let rec private visitChildren (parent: Node) (f: Node -> bool) =
Expand Down
22 changes: 22 additions & 0 deletions src/Sutil/Observable.fs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,28 @@ module Observable =
let distinctUntilChanged<'T when 'T : equality> (source:IObservable<'T>) : IObservable<'T> =
source |> distinctUntilChangedCompare (=)

/// Provide the initial value for a sequence so that new subscribers will receive an
/// immediate update of the current value
let init (v : 'T) (source: IObservable<'T>) =
let mutable current = v
{ new System.IObservable<'T> with
member _.Subscribe( h : IObserver<'T> ) =

let notify() =
try h.OnNext (current)
with ex -> h.OnError ex

let disposeA = source.Subscribe( fun x ->
current <- x
notify()
)

notify()

Helpers.disposable (fun _ -> disposeA.Dispose() )
}


/// Determines whether an observable sequence contains a specified value
/// which satisfies the given predicate
let exists predicate (source: IObservable<'T>) =
Expand Down
13 changes: 13 additions & 0 deletions src/Sutil/ObservableStore.fs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,14 @@ module ObservableStore =
let mutable name = "store-" + (string storeId)
let mutable _modelInitialized = false
let mutable _model = Unchecked.defaultof<_>
let mutable disposeListeners : (unit -> unit) list = []

let onDispose f = disposeListeners <- f :: disposeListeners

let notifyDispose() =
disposeListeners |> List.iter (fun f -> f())
disposeListeners <- []

let model() =
if not _modelInitialized then
_model <- init()
Expand Down Expand Up @@ -174,17 +182,22 @@ module ObservableStore =

member this.Name with get() = name and set (v) = name <- v

member this.OnDispose( f : unit -> unit ) =
onDispose f

member this.Dispose() =
subscribers.Values |> Seq.iter (fun x -> x.OnCompleted())
subscribers.Clear()
dispose (model())
_model <- Unchecked.defaultof<_>
Registry.notifyDisposeStore this
notifyDispose()

interface IStore<'Model> with
member this.Subscribe(observer: IObserver<'Model>) = this.Subscribe(observer)
member this.Update(f) = this.Update(f)
member this.Value = this.Value
member this.OnDispose( f : unit -> unit ) = this.OnDispose(f)
member this.Name with get() = this.Name and set (v:string) = this.Name <- v
member this.Debugger = {
new IStoreDebugger with
Expand Down
2 changes: 1 addition & 1 deletion src/Sutil/Styling.fs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ let private isClassOnly (s : string) =
let getClassMap (styleSheet) =
styleSheet
|> List.choose (fun d -> match d with Rule r when isClassOnly r.SelectorSpec -> Some (r.SelectorSpec.Substring(1),r) | _ -> None)
|> (fun items -> Fable.Core.JS.console.log("Class map: ", items |> List.map fst |> String.concat ","); items)
//|> (fun items -> Fable.Core.JS.console.log("Class map: ", items |> List.map fst |> String.concat ","); items)
|> Map


Expand Down
68 changes: 68 additions & 0 deletions src/Sutil/Sutil.fable-temp.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<!--This is a temporary file used by Fable to restore dependencies.
If you see this file in your project, you can delete it safely-->
<PropertyGroup>
<Description>Front-end framework for Fable</Description>
<Authors>David Dawkins</Authors>
<Version>2.0.13</Version>
<PackageVersion>2.0.13</PackageVersion>
<TargetFramework>netstandard2.0</TargetFramework>
<RepositoryType>git</RepositoryType>
<UsesMarkdownComments>false</UsesMarkdownComments>
<DefineConstants>$(DefineConstants);FABLE_COMPILER;</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Compile Include="Easing.fs" />
<Compile Include="Interop.fs" />
<Compile Include="Types.fs" />
<Compile Include="Logging.fs" />
<Compile Include="Helpers.fs" />
<Compile Include="Cmd.fs" />
<Compile Include="DomHelpers.fs" />
<Compile Include="Core.fs" />
<Compile Include="ResizeObserver.fs" />
<Compile Include="Styling.fs" />
<Compile Include="CoreElements.fs" />
<Compile Include="ObservableStore.fs" />
<Compile Include="Observable.fs" />
<Compile Include="Store.fs" />
<Compile Include="Promise.fs" />
<Compile Include="Transition.fs" />
<Compile Include="TransitionFunctions.fs" />
<Compile Include="Svg.fs" />
<Compile Include="Bindings.fs" />
<Compile Include="Bind.fs" />
<Compile Include="Html.fs" />
<Compile Include="Media.fs" />
<Compile Include="Navigable.fs" />
<Compile Include="Program.fs" />
<Compile Include="WebComponent.fs" />
<Compile Include="DataSimulation.fs" />
<Compile Include="Chrome.DevTools.fs" />
<Compile Include="Bulma.fs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="FSharp.Core" Version="5.0.2" />
<PackageReference Include="ConstructStyleSheetsPolyfill" Version="1.0.0-beta-001" />
<PackageReference Include="Feliz.Engine.Bulma" Version="1.0.0-*" />
<PackageReference Include="Feliz.Engine" Version="1.0.0-beta-004" />
<PackageReference Include="Feliz.Engine.Event" Version="1.0.0-beta-004" />
<PackageReference Include="Fable.Browser.Css" Version="2.*" />
<PackageReference Include="Fable.Browser.Dom" Version="2.*" />
<PackageReference Include="Fable.Browser.Event" Version="1.*" />
<PackageReference Include="Fable.Core" Version="3.*" />
<PackageReference Include="Fable.Promise" Version="3.*" />
<PackageReference Include="Fable.Browser.MediaQueryList" Version="1.*" />
</ItemGroup>
<!-- Add source files to "fable" folder in Nuget package -->
<ItemGroup>
<Content Include="*.fsproj; **\*.fs; webcomponentinterop.js;" PackagePath="fable" />
</ItemGroup>
<Target Name="ReallyClean" AfterTargets="Clean">
<!-- Remove obj folder -->
<RemoveDir Directories="$(BaseIntermediateOutputPath)" />
<!-- Remove bin folder -->
<RemoveDir Directories="$(BaseOutputPath)" />
</Target>
</Project>
3 changes: 2 additions & 1 deletion src/Sutil/Sutil.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<DefineConstants>$(DefineConstants);FABLE_COMPILER;</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Compile Include="ConstructStyleSheetsPolyfill.fs" />
<Compile Include="Easing.fs" />
<Compile Include="Interop.fs" />
<Compile Include="Types.fs" />
Expand Down Expand Up @@ -40,7 +41,7 @@
<Compile Include="Bulma.fs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="ConstructStyleSheetsPolyfill" Version="1.0.0-beta-001" />
<!-- <PackageReference Include="FSharp.Core" Version="5.0.2" /> -->
<PackageReference Include="Feliz.Engine.Bulma" Version="1.0.0-*" />
<PackageReference Include="Feliz.Engine" Version="1.0.0-beta-004" />
<PackageReference Include="Feliz.Engine.Event" Version="1.0.0-beta-004" />
Expand Down
1 change: 1 addition & 0 deletions src/Sutil/Types.fs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ type IReadOnlyStore<'T> =
inherit IObservable<'T>
inherit IDisposable
abstract Value : 'T
abstract OnDispose: (unit -> unit) -> unit

type IStore<'T> =
inherit IReadOnlyStore<'T>
Expand Down
Loading

0 comments on commit d28700e

Please sign in to comment.