From d3ec7f45e08ee0ccdf0cbbc6dbefcc07b482a9a1 Mon Sep 17 00:00:00 2001 From: Harsh Singh <64768386+harshdoesdev@users.noreply.github.com> Date: Wed, 18 Oct 2023 15:31:40 +0530 Subject: [PATCH] backdrop-filter property added (#1387) * backdrop-filter property added on containers * changed backdrop-filter to or-type * tests fixed * fixed js tests --------- Co-authored-by: heulitig --- fastn-js/js/dom.js | 88 +++++++++++++- fastn-js/src/property.rs | 2 + ftd/src/interpreter/constants.rs | 12 ++ ftd/src/interpreter/things/default.rs | 169 ++++++++++++++++++++++++++ ftd/src/js/element.rs | 16 +++ ftd/src/js/value.rs | 19 +++ ftd/t/js/66-backdrop-filter.ftd | 45 +++++++ ftd/t/js/66-backdrop-filter.html | 147 ++++++++++++++++++++++ rust-toolchain | 2 +- 9 files changed, 498 insertions(+), 2 deletions(-) create mode 100644 ftd/t/js/66-backdrop-filter.ftd create mode 100644 ftd/t/js/66-backdrop-filter.html diff --git a/fastn-js/js/dom.js b/fastn-js/js/dom.js index 0605c6d4ad..e237cc64e3 100644 --- a/fastn-js/js/dom.js +++ b/fastn-js/js/dom.js @@ -98,6 +98,7 @@ fastn_dom.propertyMap = { "z-index": "z", "-webkit-box-orient": "wbo", "-webkit-line-clamp": "wlc", + "backdrop-filter": "bdf", }; // dynamic-class-css.md @@ -278,6 +279,7 @@ fastn_dom.PropertyKind = { LinkColor: 116, TextShadow: 117, Selectable: 118, + BackdropFilter: 119, }; @@ -475,7 +477,35 @@ fastn_dom.WhiteSpace = { BreakSpaces: "break-spaces", } - +fastn_dom.BackdropFilter = { + Blur: (value) => { + return [1, value]; + }, + Brightness: (value) => { + return [2, value]; + }, + Contrast: (value) => { + return [3, value]; + }, + Grayscale: (value) => { + return [4, value]; + }, + Invert: (value) => { + return [5, value]; + }, + Opacity: (value) => { + return [6, value]; + }, + Sepia: (value) => { + return [7, value]; + }, + Saturate: (value) => { + return [8, value]; + }, + Multi: (value) => { + return [9, value]; + }, +} fastn_dom.BackgroundStyle = { Solid: (value) => { @@ -981,6 +1011,25 @@ class Node2 { this.attachCss("box-shadow", darkShadowCss, true, `body.dark .${lightClass}`); } } + attachBackdropMultiFilter(value) { + const filters = { + blur: fastn_utils.getStaticValue(value.get("blur")), + brightness: fastn_utils.getStaticValue(value.get("brightness")), + contrast: fastn_utils.getStaticValue(value.get("contrast")), + grayscale: fastn_utils.getStaticValue(value.get("grayscale")), + invert: fastn_utils.getStaticValue(value.get("invert")), + opacity: fastn_utils.getStaticValue(value.get("opacity")), + sepia: fastn_utils.getStaticValue(value.get("sepia")), + saturate: fastn_utils.getStaticValue(value.get("saturate")), + }; + + const filterString = Object.entries(filters) + .filter(([_, value]) => !fastn_utils.isNull(value)) + .map(([name, value]) => `${name}(${value})`) + .join(" "); + + this.attachCss("backdrop-filter", filterString, false); + } attachTextShadow(value) { if (fastn_utils.isNull(value)) { this.attachCss("text-shadow", value); @@ -1447,6 +1496,43 @@ class Node2 { this.attachShadow(staticValue); } else if (kind === fastn_dom.PropertyKind.TextShadow) { this.attachTextShadow(staticValue); + } else if (kind === fastn_dom.PropertyKind.BackdropFilter) { + if (fastn_utils.isNull(value)) { + this.attachCss("backdrop-filter", value); + return; + } + + let backdropType = staticValue[0]; + switch (backdropType) { + case 1: + this.attachCss("backdrop-filter", `blur(${fastn_utils.getStaticValue(staticValue[1])})`); + break; + case 2: + this.attachCss("backdrop-filter", `brightness(${fastn_utils.getStaticValue(staticValue[1])})`); + break; + case 3: + this.attachCss("backdrop-filter", `contrast(${fastn_utils.getStaticValue(staticValue[1])})`); + break; + case 4: + this.attachCss("backdrop-filter", `greyscale(${fastn_utils.getStaticValue(staticValue[1])})`); + break; + case 5: + this.attachCss("backdrop-filter", `invert(${fastn_utils.getStaticValue(staticValue[1])})`); + break; + case 6: + this.attachCss("backdrop-filter", `opacity(${fastn_utils.getStaticValue(staticValue[1])})`); + break; + case 7: + this.attachCss("backdrop-filter", `sepia(${fastn_utils.getStaticValue(staticValue[1])})`); + break; + case 8: + this.attachCss("backdrop-filter", `saturate(${fastn_utils.getStaticValue(staticValue[1])})`); + break; + case 9: + console.log("Here"); + this.attachBackdropMultiFilter(staticValue[1]); + break; + } } else if (kind === fastn_dom.PropertyKind.Classes) { fastn_utils.removeNonFastnClasses(this); if (!fastn_utils.isNull(staticValue)) { diff --git a/fastn-js/src/property.rs b/fastn-js/src/property.rs index 5907736666..174d0c52e1 100644 --- a/fastn-js/src/property.rs +++ b/fastn-js/src/property.rs @@ -426,6 +426,7 @@ pub enum PropertyKind { MetaThemeColor, Favicon, Selectable, + BackdropFilter, } impl PropertyKind { @@ -564,6 +565,7 @@ impl PropertyKind { } PropertyKind::Favicon => "fastn_dom.PropertyKind.Favicon", PropertyKind::Selectable => "fastn_dom.PropertyKind.Selectable", + PropertyKind::BackdropFilter => "fastn_dom.PropertyKind.BackdropFilter", } } } diff --git a/ftd/src/interpreter/constants.rs b/ftd/src/interpreter/constants.rs index 6ec43f22b0..2411cec670 100644 --- a/ftd/src/interpreter/constants.rs +++ b/ftd/src/interpreter/constants.rs @@ -318,3 +318,15 @@ pub const FTD_LINK_REL: &str = "ftd#link-rel"; pub const FTD_LINK_REL_NO_FOLLOW: &str = "ftd#link-rel.no-follow"; pub const FTD_LINK_REL_SPONSORED: &str = "ftd#link-rel.sponsored"; pub const FTD_LINK_REL_UGC: &str = "ftd#link-rel.ugc"; + +pub const FTD_BACKDROP_MULTI: &str = "ftd#backdrop-multi"; +pub const FTD_BACKDROP_FILTER: &str = "ftd#backdrop-filter"; +pub const FTD_BACKDROP_FILTER_BLUR: &str = "ftd#backdrop-filter.blur"; +pub const FTD_BACKDROP_FILTER_BRIGHTNESS: &str = "ftd#backdrop-filter.brightness"; +pub const FTD_BACKDROP_FILTER_CONTRAST: &str = "ftd#backdrop-filter.contrast"; +pub const FTD_BACKDROP_FILTER_GRAYSCALE: &str = "ftd#backdrop-filter.grayscale"; +pub const FTD_BACKDROP_FILTER_INVERT: &str = "ftd#backdrop-filter.invert"; +pub const FTD_BACKDROP_FILTER_OPACITY: &str = "ftd#backdrop-filter.opacity"; +pub const FTD_BACKDROP_FILTER_SEPIA: &str = "ftd#backdrop-filter.sepia"; +pub const FTD_BACKDROP_FILTER_SATURATE: &str = "ftd#backdrop-filter.saturate"; +pub const FTD_BACKDROP_FILTER_MULTI: &str = "ftd#backdrop-filter.multi"; diff --git a/ftd/src/interpreter/things/default.rs b/ftd/src/interpreter/things/default.rs index cdccf97476..df11ec6065 100644 --- a/ftd/src/interpreter/things/default.rs +++ b/ftd/src/interpreter/things/default.rs @@ -1218,6 +1218,169 @@ pub fn default_bag() -> indexmap::IndexMap { line_number: 0, }), ), + ( + ftd::interpreter::FTD_BACKDROP_FILTER.to_string(), + ftd::interpreter::Thing::OrType(ftd::interpreter::OrType { + name: ftd::interpreter::FTD_BACKDROP_FILTER.to_string(), + variants: vec![ + ftd::interpreter::OrTypeVariant::Regular(ftd::interpreter::Field::new( + ftd::interpreter::FTD_BACKDROP_FILTER_BLUR, + ftd::interpreter::Kind::or_type(ftd::interpreter::FTD_LENGTH) + .into_kind_data(), + false, + None, + 0, + )), + ftd::interpreter::OrTypeVariant::Regular(ftd::interpreter::Field::new( + ftd::interpreter::FTD_BACKDROP_FILTER_BRIGHTNESS, + ftd::interpreter::Kind::or_type(ftd::interpreter::FTD_LENGTH) + .into_kind_data(), + false, + None, + 0, + )), + ftd::interpreter::OrTypeVariant::Regular(ftd::interpreter::Field::new( + ftd::interpreter::FTD_BACKDROP_FILTER_CONTRAST, + ftd::interpreter::Kind::or_type(ftd::interpreter::FTD_LENGTH) + .into_kind_data(), + false, + None, + 0, + )), + ftd::interpreter::OrTypeVariant::Regular(ftd::interpreter::Field::new( + ftd::interpreter::FTD_BACKDROP_FILTER_GRAYSCALE, + ftd::interpreter::Kind::or_type(ftd::interpreter::FTD_LENGTH) + .into_kind_data(), + false, + None, + 0, + )), + ftd::interpreter::OrTypeVariant::Regular(ftd::interpreter::Field::new( + ftd::interpreter::FTD_BACKDROP_FILTER_INVERT, + ftd::interpreter::Kind::or_type(ftd::interpreter::FTD_LENGTH) + .into_kind_data(), + false, + None, + 0, + )), + ftd::interpreter::OrTypeVariant::Regular(ftd::interpreter::Field::new( + ftd::interpreter::FTD_BACKDROP_FILTER_OPACITY, + ftd::interpreter::Kind::or_type(ftd::interpreter::FTD_LENGTH) + .into_kind_data(), + false, + None, + 0, + )), + ftd::interpreter::OrTypeVariant::Regular(ftd::interpreter::Field::new( + ftd::interpreter::FTD_BACKDROP_FILTER_SEPIA, + ftd::interpreter::Kind::or_type(ftd::interpreter::FTD_LENGTH) + .into_kind_data(), + false, + None, + 0, + )), + ftd::interpreter::OrTypeVariant::Regular(ftd::interpreter::Field::new( + ftd::interpreter::FTD_BACKDROP_FILTER_SATURATE, + ftd::interpreter::Kind::or_type(ftd::interpreter::FTD_LENGTH) + .into_kind_data(), + false, + None, + 0, + )), + ftd::interpreter::OrTypeVariant::Regular(ftd::interpreter::Field::new( + ftd::interpreter::FTD_BACKDROP_FILTER_MULTI, + ftd::interpreter::Kind::record(ftd::interpreter::FTD_BACKDROP_MULTI) + .into_kind_data(), + false, + None, + 0, + )), + ], + line_number: 0, + }), + ), + // TODO: Instead of default value, make the integer optional + ( + ftd::interpreter::FTD_BACKDROP_MULTI.to_string(), + ftd::interpreter::Thing::Record(ftd::interpreter::Record { + name: ftd::interpreter::FTD_BACKDROP_MULTI.to_string(), + fields: std::iter::IntoIterator::into_iter([ + ftd::interpreter::Field { + name: "blur".to_string(), + kind: ftd::interpreter::Kind::or_type(ftd::interpreter::FTD_LENGTH) + .into_kind_data().into_optional(), + mutable: false, + value: None, + access_modifier: Default::default(), + line_number: 0, + }, + ftd::interpreter::Field { + name: "brightness".to_string(), + kind: ftd::interpreter::Kind::or_type(ftd::interpreter::FTD_LENGTH) + .into_kind_data().into_optional(), + mutable: false, + value: None, + access_modifier: Default::default(), + line_number: 0, + }, + ftd::interpreter::Field { + name: "contrast".to_string(), + kind: ftd::interpreter::Kind::or_type(ftd::interpreter::FTD_LENGTH) + .into_kind_data().into_optional(), + mutable: false, + value: None, + access_modifier: Default::default(), + line_number: 0, + }, + ftd::interpreter::Field { + name: "grayscale".to_string(), + kind: ftd::interpreter::Kind::or_type(ftd::interpreter::FTD_LENGTH) + .into_kind_data().into_optional(), + mutable: false, + value: None, + access_modifier: Default::default(), + line_number: 0, + }, + ftd::interpreter::Field { + name: "invert".to_string(), + kind: ftd::interpreter::Kind::or_type(ftd::interpreter::FTD_LENGTH) + .into_kind_data().into_optional(), + mutable: false, + value: None, + access_modifier: Default::default(), + line_number: 0, + }, + ftd::interpreter::Field { + name: "opacity".to_string(), + kind: ftd::interpreter::Kind::or_type(ftd::interpreter::FTD_LENGTH) + .into_kind_data().into_optional(), + mutable: false, + value: None, + access_modifier: Default::default(), + line_number: 0, + }, + ftd::interpreter::Field { + name: "sepia".to_string(), + kind: ftd::interpreter::Kind::or_type(ftd::interpreter::FTD_LENGTH) + .into_kind_data().into_optional(), + mutable: false, + value: None, + access_modifier: Default::default(), + line_number: 0, + }, + ftd::interpreter::Field { + name: "saturate".to_string(), + kind: ftd::interpreter::Kind::or_type(ftd::interpreter::FTD_LENGTH) + .into_kind_data().into_optional(), + mutable: false, + value: None, + access_modifier: Default::default(), + line_number: 0, + }, + ]).collect(), + line_number: 0, + }), + ), ( ftd::interpreter::FTD_LENGTH_PAIR.to_string(), ftd::interpreter::Thing::Record(ftd::interpreter::Record { @@ -10300,6 +10463,12 @@ fn container_arguments() -> Vec { .into_optional() .into_kind_data(), ), + ftd::interpreter::Argument::default( + "backdrop-filter", + ftd::interpreter::Kind::or_type(ftd::interpreter::FTD_BACKDROP_FILTER) + .into_optional() + .into_kind_data(), + ), ] } diff --git a/ftd/src/js/element.rs b/ftd/src/js/element.rs index 9f450463ff..5ed6088b00 100644 --- a/ftd/src/js/element.rs +++ b/ftd/src/js/element.rs @@ -930,6 +930,7 @@ pub struct ContainerProperties { pub spacing: Option, pub wrap: Option, pub align_content: Option, + pub backdrop_filter: Option, } impl ContainerProperties { @@ -945,6 +946,11 @@ impl ContainerProperties { properties, arguments, ), + backdrop_filter: ftd::js::value::get_optional_js_value( + "backdrop-filter", + properties, + arguments, + ), } } @@ -976,6 +982,16 @@ impl ContainerProperties { spacing.to_set_property(fastn_js::PropertyKind::Spacing, doc, element_name, rdata), )); } + if let Some(ref backdrop_filter) = self.backdrop_filter { + component_statements.push(fastn_js::ComponentStatement::SetProperty( + backdrop_filter.to_set_property( + fastn_js::PropertyKind::BackdropFilter, + doc, + element_name, + rdata, + ), + )); + } component_statements } } diff --git a/ftd/src/js/value.rs b/ftd/src/js/value.rs index f7875f197d..656e07395c 100644 --- a/ftd/src/js/value.rs +++ b/ftd/src/js/value.rs @@ -533,6 +533,10 @@ fn ftd_to_js_variant(name: &str, variant: &str) -> (String, bool) { let js_variant = object_fit_variants(variant); (format!("fastn_dom.Fit.{}", js_variant), false) } + "ftd#backdrop-filter" => { + let js_variant = backdrop_filter_variants(variant); + (format!("fastn_dom.BackdropFilter.{}", js_variant), true) + } t => todo!("{} {}", t, variant), } } @@ -881,3 +885,18 @@ fn object_fit_variants(name: &str) -> &'static str { t => todo!("invalid object fit variant {}", t), } } + +fn backdrop_filter_variants(name: &str) -> &'static str { + match name { + "blur" => "Blur", + "brightness" => "Brightness", + "contrast" => "Contrast", + "grayscale" => "Grayscale", + "invert" => "Invert", + "opacity" => "Opacity", + "sepia" => "Sepia", + "saturate" => "Saturate", + "multi" => "Multi", + t => unimplemented!("invalid backdrop filter variant {}", t), + } +} diff --git a/ftd/t/js/66-backdrop-filter.ftd b/ftd/t/js/66-backdrop-filter.ftd new file mode 100644 index 0000000000..2df0460aa6 --- /dev/null +++ b/ftd/t/js/66-backdrop-filter.ftd @@ -0,0 +1,45 @@ +-- ftd.backdrop-multi bdf: +blur.px: 10 +brightness.percent: 50 +contrast.percent: 40 +grayscale.percent: 40 +/invert.percent: 70 +/opacity.percent: 20 +/sepia.percent: 90 +/saturate.percent: 80 + + +;; All of the above properties (which have been commented) are supported + + + +-- boolean $blur-image: false +-- boolean $contrast-image: false +-- boolean $set-multi-filters: false + + +-- ftd.image: https://picsum.photos/200 +id: test +width.fixed.px: 300 +height.fixed.px: 300 + + + +-- ftd.row: +anchor.id: test +width.fixed.px: 300 +height.fixed.px: 300 +backdrop-filter.blur.px if { blur-image }: 10 +backdrop-filter.contrast.percent if { contrast-image }: 30 +backdrop-filter.multi if { set-multi-filters }: $bdf + + + +-- ftd.text: >> Blur/Unblur Image << +$on-click$: $ftd.toggle($a = $blur-image) + +-- ftd.text: >> Set/Unset Contrast on Image << +$on-click$: $ftd.toggle($a = $contrast-image) + +-- ftd.text: >> Set/Unset Multi << +$on-click$: $ftd.toggle($a = $set-multi-filters) diff --git a/ftd/t/js/66-backdrop-filter.html b/ftd/t/js/66-backdrop-filter.html new file mode 100644 index 0000000000..158e8b5f00 --- /dev/null +++ b/ftd/t/js/66-backdrop-filter.html @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + +
>> Blur/Unblur Image <<
>> Set/Unset Contrast on Image <<
>> Set/Unset Multi <<
+ + diff --git a/rust-toolchain b/rust-toolchain index 5e3a425662..0834888f55 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -1.73.0 +1.72.0