forked from MapComplete/MapComplete
		
	First version with working level selector
This commit is contained in:
		
							parent
							
								
									15e6fde194
								
							
						
					
					
						commit
						707961761c
					
				
					 9 changed files with 266 additions and 121 deletions
				
			
		| 
						 | 
					@ -1,10 +1,9 @@
 | 
				
			||||||
import {UIEventSource} from "../../UIEventSource";
 | 
					import {Store, UIEventSource} from "../../UIEventSource";
 | 
				
			||||||
import FilteredLayer from "../../../Models/FilteredLayer";
 | 
					import FilteredLayer, {FilterState} from "../../../Models/FilteredLayer";
 | 
				
			||||||
import {FeatureSourceForLayer, Tiled} from "../FeatureSource";
 | 
					import {FeatureSourceForLayer, Tiled} from "../FeatureSource";
 | 
				
			||||||
import {BBox} from "../../BBox";
 | 
					import {BBox} from "../../BBox";
 | 
				
			||||||
import {ElementStorage} from "../../ElementStorage";
 | 
					import {ElementStorage} from "../../ElementStorage";
 | 
				
			||||||
import {TagsFilter} from "../../Tags/TagsFilter";
 | 
					import {TagsFilter} from "../../Tags/TagsFilter";
 | 
				
			||||||
import {tag} from "@turf/turf";
 | 
					 | 
				
			||||||
import {OsmFeature} from "../../../Models/OsmFeature";
 | 
					import {OsmFeature} from "../../../Models/OsmFeature";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class FilteringFeatureSource implements FeatureSourceForLayer, Tiled {
 | 
					export default class FilteringFeatureSource implements FeatureSourceForLayer, Tiled {
 | 
				
			||||||
| 
						 | 
					@ -16,7 +15,9 @@ export default class FilteringFeatureSource implements FeatureSourceForLayer, Ti
 | 
				
			||||||
    public readonly bbox: BBox
 | 
					    public readonly bbox: BBox
 | 
				
			||||||
    private readonly upstream: FeatureSourceForLayer;
 | 
					    private readonly upstream: FeatureSourceForLayer;
 | 
				
			||||||
    private readonly state: {
 | 
					    private readonly state: {
 | 
				
			||||||
        locationControl: UIEventSource<{ zoom: number }>; selectedElement: UIEventSource<any>,
 | 
					        locationControl: Store<{ zoom: number }>; 
 | 
				
			||||||
 | 
					        selectedElement: Store<any>,
 | 
				
			||||||
 | 
					        globalFilters: Store<{ filter: FilterState }[]>,
 | 
				
			||||||
        allElements: ElementStorage
 | 
					        allElements: ElementStorage
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    private readonly _alreadyRegistered = new Set<UIEventSource<any>>();
 | 
					    private readonly _alreadyRegistered = new Set<UIEventSource<any>>();
 | 
				
			||||||
| 
						 | 
					@ -25,9 +26,10 @@ export default class FilteringFeatureSource implements FeatureSourceForLayer, Ti
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(
 | 
					    constructor(
 | 
				
			||||||
        state: {
 | 
					        state: {
 | 
				
			||||||
            locationControl: UIEventSource<{ zoom: number }>,
 | 
					            locationControl: Store<{ zoom: number }>,
 | 
				
			||||||
            selectedElement: UIEventSource<any>,
 | 
					            selectedElement: Store<any>,
 | 
				
			||||||
            allElements: ElementStorage
 | 
					            allElements: ElementStorage,
 | 
				
			||||||
 | 
					            globalFilters: Store<{ filter: FilterState }[]>
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        tileIndex,
 | 
					        tileIndex,
 | 
				
			||||||
        upstream: FeatureSourceForLayer,
 | 
					        upstream: FeatureSourceForLayer,
 | 
				
			||||||
| 
						 | 
					@ -61,6 +63,10 @@ export default class FilteringFeatureSource implements FeatureSourceForLayer, Ti
 | 
				
			||||||
            self._is_dirty.setData(true)
 | 
					            self._is_dirty.setData(true)
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
					        state.globalFilters.addCallback(_ => {
 | 
				
			||||||
 | 
					            self.update()
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.update();
 | 
					        this.update();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -69,6 +75,7 @@ export default class FilteringFeatureSource implements FeatureSourceForLayer, Ti
 | 
				
			||||||
        const layer = this.upstream.layer;
 | 
					        const layer = this.upstream.layer;
 | 
				
			||||||
        const features: { feature: OsmFeature; freshness: Date }[] = (this.upstream.features.data ?? []);
 | 
					        const features: { feature: OsmFeature; freshness: Date }[] = (this.upstream.features.data ?? []);
 | 
				
			||||||
        const includedFeatureIds = new Set<string>();
 | 
					        const includedFeatureIds = new Set<string>();
 | 
				
			||||||
 | 
					        const globalFilters = self.state.globalFilters.data.map(f => f.filter);
 | 
				
			||||||
        const newFeatures = (features ?? []).filter((f) => {
 | 
					        const newFeatures = (features ?? []).filter((f) => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            self.registerCallback(f.feature)
 | 
					            self.registerCallback(f.feature)
 | 
				
			||||||
| 
						 | 
					@ -88,6 +95,14 @@ export default class FilteringFeatureSource implements FeatureSourceForLayer, Ti
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for (const filter of globalFilters) {
 | 
				
			||||||
 | 
					                const neededTags: TagsFilter = filter?.currentFilter
 | 
				
			||||||
 | 
					                if (neededTags !== undefined && !neededTags.matchesProperties(f.feature.properties)) {
 | 
				
			||||||
 | 
					                    // Hidden by the filter on the layer itself - we want to hide it no matter what
 | 
				
			||||||
 | 
					                    return false;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            includedFeatureIds.add(f.feature.properties.id)
 | 
					            includedFeatureIds.add(f.feature.properties.id)
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,6 +8,7 @@ import {FixedUiElement} from "../UI/Base/FixedUiElement";
 | 
				
			||||||
import LayerConfig from "../Models/ThemeConfig/LayerConfig";
 | 
					import LayerConfig from "../Models/ThemeConfig/LayerConfig";
 | 
				
			||||||
import {CountryCoder} from "latlon2country"
 | 
					import {CountryCoder} from "latlon2country"
 | 
				
			||||||
import Constants from "../Models/Constants";
 | 
					import Constants from "../Models/Constants";
 | 
				
			||||||
 | 
					import {TagUtils} from "./Tags/TagUtils";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class SimpleMetaTagger {
 | 
					export class SimpleMetaTagger {
 | 
				
			||||||
| 
						 | 
					@ -32,7 +33,7 @@ export class SimpleMetaTagger {
 | 
				
			||||||
        if (!docs.cleanupRetagger) {
 | 
					        if (!docs.cleanupRetagger) {
 | 
				
			||||||
            for (const key of docs.keys) {
 | 
					            for (const key of docs.keys) {
 | 
				
			||||||
                if (!key.startsWith('_') && key.toLowerCase().indexOf("theme") < 0) {
 | 
					                if (!key.startsWith('_') && key.toLowerCase().indexOf("theme") < 0) {
 | 
				
			||||||
                    throw `Incorrect metakey ${key}: it should start with underscore (_)`
 | 
					                    throw `Incorrect key for a calculated meta value '${key}': it should start with underscore (_)`
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -211,6 +212,27 @@ export default class SimpleMetaTaggers {
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					    private static levels = new SimpleMetaTagger(
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            doc: "Extract the 'level'-tag into a normalized, ';'-separated value",
 | 
				
			||||||
 | 
					            keys: ["_level"]
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        ((feature) => {
 | 
				
			||||||
 | 
					            if (feature.properties["level"] === undefined) {
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            const l = feature.properties["level"]
 | 
				
			||||||
 | 
					            const newValue = TagUtils.LevelsParser(l).join(";")
 | 
				
			||||||
 | 
					            if(l === newValue) {
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            feature.properties["level"] = newValue
 | 
				
			||||||
 | 
					            return true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private static canonicalize = new SimpleMetaTagger(
 | 
					    private static canonicalize = new SimpleMetaTagger(
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            doc: "If 'units' is defined in the layoutConfig, then this metatagger will rewrite the specified keys to have the canonical form (e.g. `1meter` will be rewritten to `1m`)",
 | 
					            doc: "If 'units' is defined in the layoutConfig, then this metatagger will rewrite the specified keys to have the canonical form (e.g. `1meter` will be rewritten to `1m`)",
 | 
				
			||||||
| 
						 | 
					@ -327,13 +349,13 @@ export default class SimpleMetaTaggers {
 | 
				
			||||||
                        delete tags._isOpen
 | 
					                        delete tags._isOpen
 | 
				
			||||||
                        tags["_isOpen"] = "parse_error";
 | 
					                        tags["_isOpen"] = "parse_error";
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }});
 | 
					                }
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            const tagsSource = state.allElements.getEventSourceById(feature.properties.id);
 | 
					            const tagsSource = state.allElements.getEventSourceById(feature.properties.id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    private static directionSimplified = new SimpleMetaTagger(
 | 
					    private static directionSimplified = new SimpleMetaTagger(
 | 
				
			||||||
| 
						 | 
					@ -400,7 +422,8 @@ export default class SimpleMetaTaggers {
 | 
				
			||||||
        SimpleMetaTaggers.currentTime,
 | 
					        SimpleMetaTaggers.currentTime,
 | 
				
			||||||
        SimpleMetaTaggers.objectMetaInfo,
 | 
					        SimpleMetaTaggers.objectMetaInfo,
 | 
				
			||||||
        SimpleMetaTaggers.noBothButLeftRight,
 | 
					        SimpleMetaTaggers.noBothButLeftRight,
 | 
				
			||||||
        SimpleMetaTaggers.geometryType
 | 
					        SimpleMetaTaggers.geometryType,
 | 
				
			||||||
 | 
					        SimpleMetaTaggers.levels
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ];
 | 
					    ];
 | 
				
			||||||
    public static readonly lazyTags: string[] = [].concat(...SimpleMetaTaggers.metatags.filter(tagger => tagger.isLazy)
 | 
					    public static readonly lazyTags: string[] = [].concat(...SimpleMetaTaggers.metatags.filter(tagger => tagger.isLazy)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -581,4 +581,38 @@ export class TagUtils {
 | 
				
			||||||
        return listToFilter.some(tf => guards.some(guard => guard.shadows(tf)))
 | 
					        return listToFilter.some(tf => guards.some(guard => guard.shadows(tf)))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Parses a level specifier to the various available levels
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * TagUtils.LevelsParser("0") // => ["0"]
 | 
				
			||||||
 | 
					     * TagUtils.LevelsParser("1") // => ["1"]
 | 
				
			||||||
 | 
					     * TagUtils.LevelsParser("0;2") // => ["0","2"]
 | 
				
			||||||
 | 
					     * TagUtils.LevelsParser("0-5") // => ["0","1","2","3","4","5"]
 | 
				
			||||||
 | 
					     * TagUtils.LevelsParser("0") // => ["0"]
 | 
				
			||||||
 | 
					     * TagUtils.LevelsParser("-1") // => ["-1"]
 | 
				
			||||||
 | 
					     * TagUtils.LevelsParser("0;-1") // => ["0", "-1"]
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static LevelsParser(level: string): string[] {
 | 
				
			||||||
 | 
					        let spec = Utils.NoNull([level])
 | 
				
			||||||
 | 
					        spec = [].concat(...spec.map(s => s?.split(";")))
 | 
				
			||||||
 | 
					        spec = [].concat(...spec.map(s => {
 | 
				
			||||||
 | 
					            s = s.trim()
 | 
				
			||||||
 | 
					            if (s.indexOf("-") < 0 || s.startsWith("-")) {
 | 
				
			||||||
 | 
					                return s
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            const [start, end] = s.split("-").map(s => Number(s.trim()))
 | 
				
			||||||
 | 
					            if (isNaN(start) || isNaN(end)) {
 | 
				
			||||||
 | 
					                return undefined
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            const values = []
 | 
				
			||||||
 | 
					            for (let i = start; i <= end; i++) {
 | 
				
			||||||
 | 
					                values.push(i + "")
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return values
 | 
				
			||||||
 | 
					        }))
 | 
				
			||||||
 | 
					        return Utils.NoNull(spec);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -7,6 +7,11 @@ import MapState from "../../Logic/State/MapState";
 | 
				
			||||||
import LevelSelector from "../Input/LevelSelector";
 | 
					import LevelSelector from "../Input/LevelSelector";
 | 
				
			||||||
import FeaturePipeline from "../../Logic/FeatureSource/FeaturePipeline";
 | 
					import FeaturePipeline from "../../Logic/FeatureSource/FeaturePipeline";
 | 
				
			||||||
import {Utils} from "../../Utils";
 | 
					import {Utils} from "../../Utils";
 | 
				
			||||||
 | 
					import {TagUtils} from "../../Logic/Tags/TagUtils";
 | 
				
			||||||
 | 
					import {RegexTag} from "../../Logic/Tags/RegexTag";
 | 
				
			||||||
 | 
					import {Or} from "../../Logic/Tags/Or";
 | 
				
			||||||
 | 
					import {Tag} from "../../Logic/Tags/Tag";
 | 
				
			||||||
 | 
					import {TagsFilter} from "../../Logic/Tags/TagsFilter";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class RightControls extends Combine {
 | 
					export default class RightControls extends Combine {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,21 +52,67 @@ export default class RightControls extends Combine {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            const allElements = state.featurePipeline.GetAllFeaturesAndMetaWithin(bbox);
 | 
					            const allElements = state.featurePipeline.GetAllFeaturesAndMetaWithin(bbox);
 | 
				
			||||||
            const allLevelsRaw: string[] = [].concat(...allElements.map(allElements => allElements.features.map(f => <string>f.properties["level"])))
 | 
					            const allLevelsRaw: string[] = [].concat(...allElements.map(allElements => allElements.features.map(f => <string>f.properties["level"])))
 | 
				
			||||||
            const allLevels = [].concat(...allLevelsRaw.map(l => LevelSelector.LevelsParser(l)))
 | 
					            const allLevels = [].concat(...allLevelsRaw.map(l => TagUtils.LevelsParser(l)))
 | 
				
			||||||
 | 
					            if(allLevels.indexOf("0") < 0){
 | 
				
			||||||
 | 
					                allLevels.push("0")
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            allLevels.sort((a, b) => a < b ? -1 : 1)
 | 
					            allLevels.sort((a, b) => a < b ? -1 : 1)
 | 
				
			||||||
            return Utils.Dedup(allLevels)
 | 
					            return Utils.Dedup(allLevels)
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
 | 
					        state.globalFilters.data.push({
 | 
				
			||||||
 | 
					            filter: {
 | 
				
			||||||
 | 
					                currentFilter: undefined,
 | 
				
			||||||
 | 
					                state: undefined
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            }, id: "level"
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
        const levelSelect = new LevelSelector(levelsInView)
 | 
					        const levelSelect = new LevelSelector(levelsInView)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        levelsInView.addCallbackAndRun(levelsInView => {
 | 
					        const isShown = levelsInView.map(levelsInView => levelsInView.length !== 0 && state.locationControl.data.zoom >= 17,
 | 
				
			||||||
            if(levelsInView.length <= 1){
 | 
					            [state.locationControl])
 | 
				
			||||||
                levelSelect.SetClass("invisible")
 | 
					
 | 
				
			||||||
 | 
					        function setLevelFilter() {
 | 
				
			||||||
 | 
					            const filter = state.globalFilters.data.find(gf => gf.id === "level")
 | 
				
			||||||
 | 
					            const oldState = filter.filter.state;
 | 
				
			||||||
 | 
					            if (!isShown.data) {
 | 
				
			||||||
 | 
					                filter.filter = {
 | 
				
			||||||
 | 
					                    state: "*",
 | 
				
			||||||
 | 
					                    currentFilter: undefined
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                const l = levelSelect.GetValue().data
 | 
				
			||||||
 | 
					                let neededLevel : TagsFilter =  new RegexTag("level", new RegExp("(^|;)" + l + "(;|$)"));
 | 
				
			||||||
 | 
					                if(l === "0"){
 | 
				
			||||||
 | 
					                    neededLevel = new Or([neededLevel, new Tag("level", "")])
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                filter.filter = {
 | 
				
			||||||
 | 
					                    state: l,
 | 
				
			||||||
 | 
					                    currentFilter: neededLevel
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if(filter.filter.state !== oldState){
 | 
				
			||||||
 | 
					                state.globalFilters.ping();
 | 
				
			||||||
 | 
					                console.log("Level filter is now ", filter?.filter?.currentFilter?.asHumanString(false, false, {}))
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        isShown.addCallbackAndRun(shown => {
 | 
				
			||||||
 | 
					            console.log("Is level selector shown?", shown)
 | 
				
			||||||
 | 
					            setLevelFilter()
 | 
				
			||||||
 | 
					            if (shown) {
 | 
				
			||||||
 | 
					               // levelSelect.SetClass("invisible")
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                levelSelect.RemoveClass("invisible")
 | 
					                levelSelect.RemoveClass("invisible")
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        super([levelSelect, plus, min, geolocationButton].map(el => el.SetClass("m-0.5 md:m-1")))
 | 
					        levelSelect.GetValue().addCallback(_ => setLevelFilter())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        super([new Combine([levelSelect]).SetClass(""), plus, min, geolocationButton].map(el => el.SetClass("m-0.5 md:m-1")))
 | 
				
			||||||
        this.SetClass("flex flex-col items-center")
 | 
					        this.SetClass("flex flex-col items-center")
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,7 +4,6 @@ import Combine from "../Base/Combine";
 | 
				
			||||||
import Slider from "./Slider";
 | 
					import Slider from "./Slider";
 | 
				
			||||||
import {ClickableToggle} from "./Toggle";
 | 
					import {ClickableToggle} from "./Toggle";
 | 
				
			||||||
import {FixedUiElement} from "../Base/FixedUiElement";
 | 
					import {FixedUiElement} from "../Base/FixedUiElement";
 | 
				
			||||||
import {Utils} from "../../Utils";
 | 
					 | 
				
			||||||
import {VariableUiElement} from "../Base/VariableUIElement";
 | 
					import {VariableUiElement} from "../Base/VariableUIElement";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class LevelSelector extends VariableUiElement implements InputElement<string> {
 | 
					export default class LevelSelector extends VariableUiElement implements InputElement<string> {
 | 
				
			||||||
| 
						 | 
					@ -16,11 +15,15 @@ export default class LevelSelector extends VariableUiElement implements InputEle
 | 
				
			||||||
    }) {
 | 
					    }) {
 | 
				
			||||||
        const value = options?.value ?? new UIEventSource<string>(undefined)
 | 
					        const value = options?.value ?? new UIEventSource<string>(undefined)
 | 
				
			||||||
        super(Stores.ListStabilized(currentLevels).map(levels => {
 | 
					        super(Stores.ListStabilized(currentLevels).map(levels => {
 | 
				
			||||||
 | 
					            console.log("CUrrent levels are", levels)
 | 
				
			||||||
            let slider = new Slider(0, levels.length - 1, {vertical: true});
 | 
					            let slider = new Slider(0, levels.length - 1, {vertical: true});
 | 
				
			||||||
            slider.SetClass("flex m-1 elevatorslider mb-0 mt-8").SetStyle("height: " + 2.5 * levels.length + "rem ")
 | 
					            const toggleClass = "flex border-2 border-blue-500 w-10 h-10 place-content-center items-center border-box"
 | 
				
			||||||
            const toggleClass = "flex border-2 border-blue-500 w-10 h-10 place-content-center items-center"
 | 
					            slider.SetClass("flex elevator w-10").SetStyle(`height: ${2.5 * levels.length}rem; background: #00000000`)
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
            const values = levels.map((data, i) => new ClickableToggle(
 | 
					            const values = levels.map((data, i) => new ClickableToggle(
 | 
				
			||||||
                new FixedUiElement(data).SetClass("active bg-subtle " + toggleClass), new FixedUiElement(data).SetClass(toggleClass), slider.GetValue().sync(
 | 
					                new FixedUiElement(data).SetClass("font-bold active bg-subtle " + toggleClass), 
 | 
				
			||||||
 | 
					                new FixedUiElement(data).SetClass("normal-background " + toggleClass), 
 | 
				
			||||||
 | 
					                slider.GetValue().sync(
 | 
				
			||||||
                    (sliderVal) => {
 | 
					                    (sliderVal) => {
 | 
				
			||||||
                        return sliderVal === i
 | 
					                        return sliderVal === i
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
| 
						 | 
					@ -30,10 +33,12 @@ export default class LevelSelector extends VariableUiElement implements InputEle
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                ))
 | 
					                ))
 | 
				
			||||||
                .ToggleOnClick()
 | 
					                .ToggleOnClick()
 | 
				
			||||||
                .SetClass("flex flex-column ml-5 bg-slate-200 w-10 h-10 valuesContainer"))
 | 
					                .SetClass("flex w-10 h-10"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            values.reverse(/* This is a new list, no side-effects */)
 | 
				
			||||||
 | 
					            const combine = new Combine([new Combine(values), slider])
 | 
				
			||||||
 | 
					            combine.SetClass("flex flex-row overflow-hidden");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            const combine = new Combine([new Combine(values).SetClass("mt-8"), slider])
 | 
					 | 
				
			||||||
            combine.SetClass("flex flex-row h-14");
 | 
					 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            slider.GetValue().addCallbackAndRun(i => {
 | 
					            slider.GetValue().addCallbackAndRun(i => {
 | 
				
			||||||
                if (currentLevels?.data === undefined) {
 | 
					                if (currentLevels?.data === undefined) {
 | 
				
			||||||
| 
						 | 
					@ -48,6 +53,8 @@ export default class LevelSelector extends VariableUiElement implements InputEle
 | 
				
			||||||
            return combine
 | 
					            return combine
 | 
				
			||||||
        }))
 | 
					        }))
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
					        this._value = value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    GetValue(): UIEventSource<string> {
 | 
					    GetValue(): UIEventSource<string> {
 | 
				
			||||||
| 
						 | 
					@ -59,35 +66,5 @@ export default class LevelSelector extends VariableUiElement implements InputEle
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Parses a level specifier to the various available levels
 | 
					 | 
				
			||||||
     *
 | 
					 | 
				
			||||||
     * LevelSelector.LevelsParser("0") // => ["0"]
 | 
					 | 
				
			||||||
     * LevelSelector.LevelsParser("1") // => ["1"]
 | 
					 | 
				
			||||||
     * LevelSelector.LevelsParser("0;2") // => ["0","2"]
 | 
					 | 
				
			||||||
     * LevelSelector.LevelsParser("0-5") // => ["0","1","2","3","4","5"]
 | 
					 | 
				
			||||||
     * LevelSelector.LevelsParser("0") // => ["0"]
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public static LevelsParser(level: string): string[] {
 | 
					 | 
				
			||||||
        let spec = [level]
 | 
					 | 
				
			||||||
        spec = [].concat(...spec.map(s => s.split(";")))
 | 
					 | 
				
			||||||
        spec = [].concat(...spec.map(s => {
 | 
					 | 
				
			||||||
            s = s.trim()
 | 
					 | 
				
			||||||
            if (s.indexOf("-") < 0) {
 | 
					 | 
				
			||||||
                return s
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            const [start, end] = s.split("-").map(s => Number(s.trim()))
 | 
					 | 
				
			||||||
            if (isNaN(start) || isNaN(end)) {
 | 
					 | 
				
			||||||
                return undefined
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            const values = []
 | 
					 | 
				
			||||||
            for (let i = start; i <= end; i++) {
 | 
					 | 
				
			||||||
                values.push(i + "")
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            return values
 | 
					 | 
				
			||||||
        }))
 | 
					 | 
				
			||||||
        return Utils.NoNull(spec);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1 +1,76 @@
 | 
				
			||||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 228.57 239.29"><defs><style>.cls-1{fill:#1d1d1b;}</style></defs><path class="cls-1" d="M208.18,119.08V11.93c0-5.24,0-5.24,5.15-5.24,2.43,0,4.87,0,7.31,0,2.05,0,3.12.76,3,2.92-.07,1.13,0,2.27,0,3.4q0,106.5,0,213c0,.69-.06,1.39,0,2.09.13,1.9-.73,2.68-2.62,2.64-3.39-.05-6.79,0-10.19,0-1.84,0-2.73-.76-2.66-2.67s0-4,0-6Z"/><path class="cls-1" d="M20,119.06V226.75c0,3.9,0,3.92-3.91,4-3,0-5.93-.05-8.89,0-1.76,0-2.58-.7-2.55-2.47s0-3.31,0-5q0-106.12,0-212.25c0-4.17.22-4.39,4.45-4.36,2.52,0,5.05.08,7.58,0,2.26-.09,3.47.67,3.32,3.13-.1,1.47,0,3,0,4.44q0,52.41,0,104.82Z"/><path class="cls-1" d="M135.46,156.52a4.35,4.35,0,0,0-4.86-3.21,12.64,12.64,0,0,0-2.44.73c-2.07.72-4.13,1.47-6.22,2.21l-.26-.54q-1.94-4.52-3.88-9c-1.77-4.11-3.53-8.22-5.32-12.31a4.21,4.21,0,0,0-4.06-2.71c-4.84-.06-9.68-.07-14.52-.11L81,131.46c-.18,0-.5-.09-.52-.19-.16-.78-.27-1.58-.4-2.42H99.2c.35,0,.69,0,1,0a4.41,4.41,0,0,0,3.41-6.75,4.58,4.58,0,0,0-4.22-2.1q-10,0-20,0h-.72c-.52-3.24-1-6.39-1.54-9.56h-9c.55,3.45,1.11,6.9,1.66,10.35.83,5.11,1.71,10.2,2.47,15.32a4.76,4.76,0,0,0,4.92,4.29c9.22,0,18.45.11,27.68.15a.86.86,0,0,1,.91.61q4.72,11.05,9.48,22.08a4.49,4.49,0,0,0,6.12,2.69c3.69-1.31,7.39-2.61,11.07-3.95a6.74,6.74,0,0,0,1.67-1,4.71,4.71,0,0,0,1.49-2.56v-1.48C135.55,156.8,135.5,156.66,135.46,156.52Z"/><path class="cls-1" d="M53.61,145.09c.2-1.23.33-2.47.59-3.69a26.58,26.58,0,0,1,6.42-12.56,4.42,4.42,0,0,1,6.63,5.85,18.7,18.7,0,0,0-4.46,8.95,18.32,18.32,0,0,0,34.75,10.84,4.62,4.62,0,0,1,3.67-3,4.41,4.41,0,0,1,4.76,5.84,23.53,23.53,0,0,1-3.45,6.12,26.77,26.77,0,0,1-14.83,10c-1.46.38-3,.53-4.47.79l-.56.11H78.9c-.14,0-.29-.08-.43-.1a34.79,34.79,0,0,1-3.7-.6c-11-2.89-17.86-9.91-20.58-20.95-.29-1.19-.39-2.43-.58-3.64Z"/><ellipse class="cls-1" cx="72.62" cy="109.74" rx="4.51" ry="3.94"/><circle class="cls-1" cx="71.76" cy="95.49" r="8.93"/><path class="cls-1" d="M157.33,131.79H154v1.75q0,18,0,36c0,2.4-1,3.89-2.94,4.52a4.17,4.17,0,0,1-5.43-3.17,10.86,10.86,0,0,1-.13-2q0-31,0-61.93v-2.49h-2c0,.48-.07,1-.07,1.47,0,7.32,0,14.65,0,22,0,2.28-1.42,3.66-3.4,3.39a3,3,0,0,1-2.63-3.33c0-5.24,0-10.47,0-15.7,0-4.38,0-8.75,0-13.13,0-5.09,2.76-7.89,7.83-7.92q10.48-.06,21,0c4.89,0,7.67,2.88,7.67,7.77q0,14.49,0,29c0,2.3-1.56,3.7-3.6,3.31-1.57-.3-2.41-1.44-2.41-3.35q0-10.84,0-21.69v-1.76h-2v1.76q0,31.32,0,62.64a10.81,10.81,0,0,1-.17,2.13,4.23,4.23,0,0,1-4.41,3.27,4.18,4.18,0,0,1-3.9-4c0-2.95,0-5.9,0-8.84V131.79Z"/><path class="cls-1" d="M155.74,89.56a9,9,0,0,1-9.1-9,9,9,0,0,1,18,0A9,9,0,0,1,155.74,89.56Z"/><path class="cls-1" d="M191.93,36.94h-71V24.12h10l-17-17-17,17h10V36.94h-71a5.83,5.83,0,0,0-5.83,5.83V197.05a5.83,5.83,0,0,0,5.83,5.83h71V215.7h-10l17,17,17-17h-10V202.88h71a5.83,5.83,0,0,0,5.83-5.83V42.77A5.83,5.83,0,0,0,191.93,36.94Zm-7.5,147a5.83,5.83,0,0,1-5.83,5.84H49.22a5.83,5.83,0,0,1-5.83-5.84V56a5.83,5.83,0,0,1,5.83-5.83H178.6A5.83,5.83,0,0,1,184.43,56Z"/></svg>
 | 
					<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 | 
				
			||||||
 | 
					<svg
 | 
				
			||||||
 | 
					   id="Layer_1"
 | 
				
			||||||
 | 
					   data-name="Layer 1"
 | 
				
			||||||
 | 
					   viewBox="0 0 228.57 239.29"
 | 
				
			||||||
 | 
					   version="1.1"
 | 
				
			||||||
 | 
					   sodipodi:docname="elevator_wheelchair.svg"
 | 
				
			||||||
 | 
					   inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
 | 
				
			||||||
 | 
					   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
 | 
				
			||||||
 | 
					   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
 | 
				
			||||||
 | 
					   xmlns="http://www.w3.org/2000/svg"
 | 
				
			||||||
 | 
					   xmlns:svg="http://www.w3.org/2000/svg">
 | 
				
			||||||
 | 
					  <sodipodi:namedview
 | 
				
			||||||
 | 
					     id="namedview25"
 | 
				
			||||||
 | 
					     pagecolor="#ffffff"
 | 
				
			||||||
 | 
					     bordercolor="#111111"
 | 
				
			||||||
 | 
					     borderopacity="1"
 | 
				
			||||||
 | 
					     inkscape:pageshadow="0"
 | 
				
			||||||
 | 
					     inkscape:pageopacity="0"
 | 
				
			||||||
 | 
					     inkscape:pagecheckerboard="1"
 | 
				
			||||||
 | 
					     showgrid="false"
 | 
				
			||||||
 | 
					     inkscape:zoom="1.9145025"
 | 
				
			||||||
 | 
					     inkscape:cx="60.851318"
 | 
				
			||||||
 | 
					     inkscape:cy="68.425087"
 | 
				
			||||||
 | 
					     inkscape:window-width="1920"
 | 
				
			||||||
 | 
					     inkscape:window-height="1007"
 | 
				
			||||||
 | 
					     inkscape:window-x="0"
 | 
				
			||||||
 | 
					     inkscape:window-y="0"
 | 
				
			||||||
 | 
					     inkscape:window-maximized="1"
 | 
				
			||||||
 | 
					     inkscape:current-layer="Layer_1" />
 | 
				
			||||||
 | 
					  <defs
 | 
				
			||||||
 | 
					     id="defs4">
 | 
				
			||||||
 | 
					    <style
 | 
				
			||||||
 | 
					       id="style2">.cls-1{fill:#1d1d1b;}</style>
 | 
				
			||||||
 | 
					  </defs>
 | 
				
			||||||
 | 
					  <path
 | 
				
			||||||
 | 
					     class="cls-1"
 | 
				
			||||||
 | 
					     d="m 146.05301,172.90366 a 6.4729946,6.4729946 0 0 0 -7.2319,-4.77662 18.808885,18.808885 0 0 0 -3.63083,1.08627 c -3.08025,1.07139 -6.14562,2.18743 -9.25563,3.28858 l -0.3869,-0.80354 q -2.8868,-6.72597 -5.77361,-13.39241 c -2.63384,-6.11586 -5.2528,-12.23172 -7.9164,-18.31783 a 6.2646683,6.2646683 0 0 0 -6.04146,-4.0326 c -7.202135,-0.0893 -14.404272,-0.10416 -21.606408,-0.16368 l -19.195777,-0.17857 c -0.267848,0 -0.744022,-0.13392 -0.773783,-0.28273 -0.238087,-1.16067 -0.401772,-2.35111 -0.595218,-3.60107 h 28.451415 c 0.520816,0 1.026751,0 1.488045,0 a 6.5622772,6.5622772 0 0 0 5.074232,-10.0443 6.8152448,6.8152448 0 0 0 -6.279548,-3.12489 q -14.880448,0 -29.760895,0 H 61.546951 C 60.773168,113.739 60.058906,109.05166 59.255362,104.33456 H 45.862959 c 0.818425,5.13375 1.65173,10.26751 2.470155,15.40126 1.235077,7.60391 2.544556,15.17806 3.67547,22.79685 a 7.0830929,7.0830929 0 0 0 7.32118,6.38371 c 13.719773,0 27.454425,0.16369 41.189076,0.22321 a 1.2797185,1.2797185 0 0 1 1.35412,0.9077 q 7.02357,16.4429 14.10667,32.85603 a 6.6813208,6.6813208 0 0 0 9.10683,4.00284 c 5.49089,-1.94934 10.99665,-3.88379 16.47266,-5.87777 a 10.029421,10.029421 0 0 0 2.48503,-1.48805 7.0086907,7.0086907 0 0 0 2.21719,-3.80939 v -2.20231 c -0.0744,-0.20833 -0.14881,-0.41665 -0.20833,-0.62498 z"
 | 
				
			||||||
 | 
					     id="path10"
 | 
				
			||||||
 | 
					     style="stroke-width:1.48804" />
 | 
				
			||||||
 | 
					  <path
 | 
				
			||||||
 | 
					     class="cls-1"
 | 
				
			||||||
 | 
					     d="m 24.25655,155.89531 c 0.297609,-1.83029 0.491055,-3.67547 0.877946,-5.49088 a 39.552229,39.552229 0 0 1 9.553248,-18.68985 6.5785825,6.5785825 0 0 1 9.865736,8.70507 27.826436,27.826436 0 0 0 -6.636679,13.318 27.260979,27.260979 0 0 0 51.709554,16.1304 6.8747666,6.8747666 0 0 1 5.461124,-4.46413 6.5622772,6.5622772 0 0 1 7.083091,8.69018 35.013692,35.013692 0 0 1 -5.133752,9.10683 39.834957,39.834957 0 0 1 -22.067704,14.88045 c -2.172545,0.56546 -4.464134,0.78866 -6.65156,1.17555 l -0.833305,0.16369 h -5.595048 c -0.208326,0 -0.431533,-0.11905 -0.639859,-0.14881 a 51.769076,51.769076 0 0 1 -5.505766,-0.89282 c -16.368492,-4.30045 -26.576478,-14.74653 -30.62396,-31.17454 -0.431533,-1.77077 -0.580337,-3.61595 -0.863066,-5.41648 z"
 | 
				
			||||||
 | 
					     id="path12"
 | 
				
			||||||
 | 
					     style="stroke-width:1.48804" />
 | 
				
			||||||
 | 
					  <ellipse
 | 
				
			||||||
 | 
					     class="cls-1"
 | 
				
			||||||
 | 
					     cx="52.544285"
 | 
				
			||||||
 | 
					     cy="103.29292"
 | 
				
			||||||
 | 
					     rx="6.711082"
 | 
				
			||||||
 | 
					     ry="5.8628964"
 | 
				
			||||||
 | 
					     id="ellipse14"
 | 
				
			||||||
 | 
					     style="stroke-width:1.48804" />
 | 
				
			||||||
 | 
					  <circle
 | 
				
			||||||
 | 
					     class="cls-1"
 | 
				
			||||||
 | 
					     cx="51.264565"
 | 
				
			||||||
 | 
					     cy="82.088287"
 | 
				
			||||||
 | 
					     r="13.288239"
 | 
				
			||||||
 | 
					     id="circle16"
 | 
				
			||||||
 | 
					     style="stroke-width:1.48804" />
 | 
				
			||||||
 | 
					  <path
 | 
				
			||||||
 | 
					     class="cls-1"
 | 
				
			||||||
 | 
					     d="m 178.59655,136.10432 h -4.95519 v 2.60407 q 0,26.78481 0,53.56961 c 0,3.57131 -1.48804,5.7885 -4.37485,6.72597 a 6.2051465,6.2051465 0 0 1 -8.08008,-4.71711 16.160166,16.160166 0 0 1 -0.19345,-2.97609 q 0,-46.12938 0,-92.154605 v -3.705232 h -2.97609 c 0,0.714262 -0.10416,1.488045 -0.10416,2.187426 0,10.892491 0,21.799851 0,32.736981 0,3.39275 -2.11303,5.44625 -5.05935,5.04447 a 4.4641342,4.4641342 0 0 1 -3.91356,-4.95518 c 0,-7.79736 0,-15.57983 0,-23.36231 0,-6.51763 0,-13.020388 0,-19.538024 0,-7.574147 4.107,-11.740672 11.65139,-11.785314 q 15.59471,-0.08928 31.24894,0 c 7.27654,0 11.4133,4.285569 11.4133,11.562108 q 0,21.56177 0,43.1533 c 0,3.4225 -2.32135,5.50576 -5.35696,4.92542 -2.33623,-0.44641 -3.58619,-2.14278 -3.58619,-4.98495 q 0,-16.1304 0,-32.275685 v -2.618959 h -2.97609 v 2.618959 q 0,46.605565 0,93.211125 a 16.085763,16.085763 0 0 1 -0.25297,3.16953 6.2944292,6.2944292 0 0 1 -6.56227,4.86591 6.2200269,6.2200269 0 0 1 -5.80338,-5.95218 c 0,-4.38973 0,-8.77946 0,-13.15432 v -44.19492 z"
 | 
				
			||||||
 | 
					     id="path18"
 | 
				
			||||||
 | 
					     style="stroke-width:1.48804" />
 | 
				
			||||||
 | 
					  <path
 | 
				
			||||||
 | 
					     class="cls-1"
 | 
				
			||||||
 | 
					     d="m 176.23056,73.264187 a 13.392403,13.392403 0 0 1 -13.54121,-13.392403 13.392405,13.392405 0 0 1 26.78481,0 13.392403,13.392403 0 0 1 -13.2436,13.392403 z"
 | 
				
			||||||
 | 
					     id="path20"
 | 
				
			||||||
 | 
					     style="stroke-width:1.48804" />
 | 
				
			||||||
 | 
					  <path
 | 
				
			||||||
 | 
					     class="cls-1"
 | 
				
			||||||
 | 
					     d="M 226.27477,0.4068479 H 124.01222 V -18.058024 H 138.4154 L 113.93,-42.543423 89.444601,-18.058024 H 103.84778 V 0.4068479 H 1.5852264 A 8.3970517,8.3970517 0 0 0 -6.8118252,8.8038996 V 231.0161 a 8.3970517,8.3970517 0 0 0 8.3970516,8.39705 H 103.84778 v 18.46487 H 89.444601 l 24.485399,24.4854 24.4854,-24.4854 h -14.40318 v -18.46487 h 102.26255 a 8.3970517,8.3970517 0 0 0 8.39706,-8.39705 V 8.8038996 A 8.3970517,8.3970517 0 0 0 226.27477,0.4068479 Z M 215.47239,212.13354 a 8.3970517,8.3970517 0 0 1 -8.39705,8.41145 H 20.727047 a 8.3970517,8.3970517 0 0 1 -8.397051,-8.41145 V 27.859302 A 8.3970517,8.3970517 0 0 1 20.727047,19.46225 H 207.07534 a 8.3970517,8.3970517 0 0 1 8.39705,8.397052 z"
 | 
				
			||||||
 | 
					     id="path22"
 | 
				
			||||||
 | 
					     style="stroke-width:1.44032" />
 | 
				
			||||||
 | 
					</svg>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
		 Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 5.6 KiB  | 
| 
						 | 
					@ -946,18 +946,6 @@ video {
 | 
				
			||||||
  margin-right: 0px;
 | 
					  margin-right: 0px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.mb-0 {
 | 
					 | 
				
			||||||
  margin-bottom: 0px;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.mt-8 {
 | 
					 | 
				
			||||||
  margin-top: 2rem;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.ml-5 {
 | 
					 | 
				
			||||||
  margin-left: 1.25rem;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.mr-3 {
 | 
					.mr-3 {
 | 
				
			||||||
  margin-right: 0.75rem;
 | 
					  margin-right: 0.75rem;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -974,6 +962,10 @@ video {
 | 
				
			||||||
  margin-right: 0.25rem;
 | 
					  margin-right: 0.25rem;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.mb-0 {
 | 
				
			||||||
 | 
					  margin-bottom: 0px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.box-border {
 | 
					.box-border {
 | 
				
			||||||
  box-sizing: border-box;
 | 
					  box-sizing: border-box;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1106,10 +1098,6 @@ video {
 | 
				
			||||||
  height: 4rem;
 | 
					  height: 4rem;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.h-14 {
 | 
					 | 
				
			||||||
  height: 3.5rem;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.h-0 {
 | 
					.h-0 {
 | 
				
			||||||
  height: 0px;
 | 
					  height: 0px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1527,6 +1515,11 @@ video {
 | 
				
			||||||
  background-color: rgba(224, 231, 255, var(--tw-bg-opacity));
 | 
					  background-color: rgba(224, 231, 255, var(--tw-bg-opacity));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.bg-red-500 {
 | 
				
			||||||
 | 
					  --tw-bg-opacity: 1;
 | 
				
			||||||
 | 
					  background-color: rgba(239, 68, 68, var(--tw-bg-opacity));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.bg-black {
 | 
					.bg-black {
 | 
				
			||||||
  --tw-bg-opacity: 1;
 | 
					  --tw-bg-opacity: 1;
 | 
				
			||||||
  background-color: rgba(0, 0, 0, var(--tw-bg-opacity));
 | 
					  background-color: rgba(0, 0, 0, var(--tw-bg-opacity));
 | 
				
			||||||
| 
						 | 
					@ -1547,11 +1540,6 @@ video {
 | 
				
			||||||
  background-color: rgba(209, 213, 219, var(--tw-bg-opacity));
 | 
					  background-color: rgba(209, 213, 219, var(--tw-bg-opacity));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.bg-red-500 {
 | 
					 | 
				
			||||||
  --tw-bg-opacity: 1;
 | 
					 | 
				
			||||||
  background-color: rgba(239, 68, 68, var(--tw-bg-opacity));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.bg-red-200 {
 | 
					.bg-red-200 {
 | 
				
			||||||
  --tw-bg-opacity: 1;
 | 
					  --tw-bg-opacity: 1;
 | 
				
			||||||
  background-color: rgba(254, 202, 202, var(--tw-bg-opacity));
 | 
					  background-color: rgba(254, 202, 202, var(--tw-bg-opacity));
 | 
				
			||||||
| 
						 | 
					@ -2072,29 +2060,17 @@ input[type="range"].vertical {
 | 
				
			||||||
  /* IE */
 | 
					  /* IE */
 | 
				
			||||||
  -webkit-appearance: slider-vertical;
 | 
					  -webkit-appearance: slider-vertical;
 | 
				
			||||||
  /* Chromium */
 | 
					  /* Chromium */
 | 
				
			||||||
  width: 8px;
 | 
					 | 
				
			||||||
  height: 180px;
 | 
					 | 
				
			||||||
  padding: 31px 5px 0 5px;
 | 
					 | 
				
			||||||
  cursor: pointer;
 | 
					  cursor: pointer;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@-moz-document url-prefix() {
 | 
					@-moz-document url-prefix() {
 | 
				
			||||||
  input[type="range"].vertical {
 | 
					  input[type="range"].elevator::-moz-range-thumb {
 | 
				
			||||||
    height: 269px !important;
 | 
					 | 
				
			||||||
    width: 65px !important;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  .valuesContainer {
 | 
					 | 
				
			||||||
    padding-top: 30px;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  input[type="range"].vertical::-moz-range-thumb {
 | 
					 | 
				
			||||||
    width: 150px;
 | 
					 | 
				
			||||||
    height: 30px;
 | 
					 | 
				
			||||||
    border: 2px;
 | 
					 | 
				
			||||||
    border-style: solid;
 | 
					 | 
				
			||||||
    background-color: #00000000 !important;
 | 
					    background-color: #00000000 !important;
 | 
				
			||||||
    background-image: url("/assets/svg/elevator_wheelchair.svg");
 | 
					    background-image: url("/assets/svg/elevator_wheelchair.svg");
 | 
				
			||||||
 | 
					    width: 150px !important;
 | 
				
			||||||
 | 
					    height: 30px !important;
 | 
				
			||||||
 | 
					    border: 2px;
 | 
				
			||||||
 | 
					    border-style: solid;
 | 
				
			||||||
    background-size: contain;
 | 
					    background-size: contain;
 | 
				
			||||||
    background-position: center center;
 | 
					    background-position: center center;
 | 
				
			||||||
    background-repeat: no-repeat;
 | 
					    background-repeat: no-repeat;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										20
									
								
								index.css
									
										
									
									
									
								
							
							
						
						
									
										20
									
								
								index.css
									
										
									
									
									
								
							| 
						 | 
					@ -232,27 +232,17 @@ a {
 | 
				
			||||||
input[type="range"].vertical {
 | 
					input[type="range"].vertical {
 | 
				
			||||||
  writing-mode: bt-lr; /* IE */
 | 
					  writing-mode: bt-lr; /* IE */
 | 
				
			||||||
  -webkit-appearance: slider-vertical; /* Chromium */
 | 
					  -webkit-appearance: slider-vertical; /* Chromium */
 | 
				
			||||||
  width: 8px;
 | 
					 | 
				
			||||||
  height: 180px;
 | 
					 | 
				
			||||||
  padding: 31px 5px 0 5px;
 | 
					 | 
				
			||||||
  cursor: pointer;
 | 
					  cursor: pointer;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@-moz-document url-prefix() {
 | 
					@-moz-document url-prefix() {
 | 
				
			||||||
  input[type="range"].vertical {
 | 
					  input[type="range"].elevator::-moz-range-thumb {
 | 
				
			||||||
    height: 269px !important;
 | 
					 | 
				
			||||||
    width: 65px !important;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  .valuesContainer {
 | 
					 | 
				
			||||||
    padding-top: 30px;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  input[type="range"].vertical::-moz-range-thumb {
 | 
					 | 
				
			||||||
    width: 150px;
 | 
					 | 
				
			||||||
    height: 30px;
 | 
					 | 
				
			||||||
    border: 2px;
 | 
					 | 
				
			||||||
    border-style: solid;
 | 
					 | 
				
			||||||
    background-color: #00000000 !important;
 | 
					    background-color: #00000000 !important;
 | 
				
			||||||
    background-image: url("/assets/svg/elevator_wheelchair.svg");
 | 
					    background-image: url("/assets/svg/elevator_wheelchair.svg");
 | 
				
			||||||
 | 
					    width: 150px !important;
 | 
				
			||||||
 | 
					    height: 30px !important;
 | 
				
			||||||
 | 
					    border: 2px;
 | 
				
			||||||
 | 
					    border-style: solid;
 | 
				
			||||||
    background-size: contain;
 | 
					    background-size: contain;
 | 
				
			||||||
    background-position: center center;
 | 
					    background-position: center center;
 | 
				
			||||||
    background-repeat: no-repeat;
 | 
					    background-repeat: no-repeat;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										4
									
								
								test.ts
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								test.ts
									
										
									
									
									
								
							| 
						 | 
					@ -0,0 +1,4 @@
 | 
				
			||||||
 | 
					import LevelSelector from "./UI/Input/LevelSelector";
 | 
				
			||||||
 | 
					import {UIEventSource} from "./Logic/UIEventSource";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					new LevelSelector(new UIEventSource(["0","1","2","2.5","x","3"])).AttachTo("maindiv")
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue