npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

hart-estate-widget

v4.7.0-stage.12

Published

HART Estate widget

Downloads

2,378

Readme

HART Estate Widget

The package is designed to present 2D and 3D floor plans generated by the AI service getfloorplan.com.

Table of Contents

Quick Start

As a result, you will receive a website that can display various floor plans.

node: ^18.0.0

  • Download NodeJS 18+
  • Create a new project
npm init
  • Download the required packages
npm install -S [email protected]  # GFP Widget package
npm install -S -D vite                   # Vite bundler
npm install -S -D sass-embedded          # Sass style compiler
  • Example structure of project
.
├── src
│   ├── index.html
│   ├── index.js
│   ├── index.sass
│   └── logo.png
├── package.json
└── package-lock.json
  • Copy-paste sample assets from below.
  • Run with rm -rf dist && npx vite
  • Open browser at: http://localhost:1234/?id=73b833c3-072a-4ac2-9f5d-7f7ac3d1fc9c

The query id parameter accepts the UUID4 received from getfloorplan.com You can use these UUID4 for test purposes:

  • Scandy style: 228ba1dd-64d3-4d33-bcd7-b4c670bed40e
  • Boho style: f9032373-bb2c-416e-b0ab-20b8fd24d482
  • England style: b21871a2-2d5b-4beb-817b-ed750eebab9a
  • Neutral style: e8553134-0457-488c-8d3e-611b0e2be4d4
  • Modern style: 73b833c3-072a-4ac2-9f5d-7f7ac3d1fc9c

VITE

Insert the example into a file vite.config.ts

import { defineConfig } from 'vite';

export default defineConfig({
  root: 'src',
  build: { outDir: '../dist' },
  server: { port: 1234, open: true },
});

HTML

Insert the example into a file src/index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0" />
    <title>HART Estate Widget</title>

    <script type="module" src="./index.js"></script>
    <link rel="icon" href="./logo.png">
  </head>

  <body>
    <div id="widget"></div>
  </body>
</html>

JavaScript

Insert the example into a file src/index.js

import { Api } from 'hart-estate-widget/build/api.js';
import { usePreloader } from 'hart-estate-widget/build/usePreloader.js';

const searchParams = new URLSearchParams(document.location.search);
const planId = searchParams.get('id');
const crmPlanId = searchParams.get('crmPlanId');

const baseUrl = 'https://backend.estate.hart-digital.com';

const loadData = async () => {
  const {loadCrmWidgetData, loadWidgetData} = new Api(baseUrl);
  return crmPlanId ? loadCrmWidgetData(crmPlanId) : loadWidgetData(planId);
};
const loadCreateWidget = async () => (await import('hart-estate-widget/build/createWidget.js')).createWidget;
const loadFovPlugin = async () => (await import('hart-estate-widget/build/plugins/FovPlugin.js')).FovPlugin;
const loadLogoUrl = async () => (await import('./logo.png')).default;
const loadStyle = async () => (await import('./index.sass')).default;
const loadDocument = async () => new Promise((resolve) => (window.onload = resolve));

const queue = [
  loadData(),
  loadCreateWidget(),
  loadFovPlugin(),
  loadLogoUrl(),
  loadStyle(),
  loadDocument(),
];

const cleanupPreloader = usePreloader();

Promise.all(queue).then(([data, createWidget, FovPlugin, logoUrl]) => {
  const options = {
    baseUrl,
    logoUrl,
    logoLinkUrl: 'https://getfloorplan.com',
  };

  const plugins = [
    new FovPlugin(2),
  ];

  createWidget('#widget', data, options, plugins).then(cleanupPreloader);
});

SASS

Insert the example into a file src/index.sass

*, *:before, *:after
  -webkit-font-smoothing: antialiased
  -moz-osx-font-smoothing: grayscale
  font-family: 'Proxima Nova', sans-serif
  text-decoration: none
  font-weight: 400
  color: #fff
  outline: none
  padding: 0
  margin: 0
  box-sizing: border-box
  -webkit-box-sizing: border-box

html, body
  width: 100%
  height: 100%

#widget
  width: 100%
  height: 100%
  overflow: hidden

Docs

Parameters:

Here you can see a list of accessible options and examples of usage. There are accessible values for each option below in the block "Types of Elements".

{
  // Widget API base URL
  "baseUrl": "https://backend.estate.hart-digital.com",

  // Widget locale can be one of
  // "en" - English language
  // "ru" - Russian language
  // "de" - German language
  // "es" - Spanish language
  // "ja" - Japanese language
  // "nl" - Dutch language
  // "bg" - Bulgarian language
  // "he" - Hebrew language
  "locale": "en",

  // Path/link to the logo
  "logoUrl": "https://getfloorplan.com/img/logo.58f6cd11.svg",
  // Link opened when logo is clicked
  "logoLinkUrl": "https://getfloorplan.com",
  // Widget color settings in CSS color formal like: "rgba(255, 255, 255, 0)", "#ABCDEF", etc...
  // "main" - main color of buttons, elements
  // "mainText" - text color for buttons, elements contrasting with the main color
  "colors": {
    "main": "#FFA900",
    "mainText": "#413E3E"
  },

  // First opened tab
  "primaryTab": "panorama",
  // Available widget tabs array with order:
  // "vr" - VR button
  // "panorama" - Panorama 360 tab
  // "rotation" - Isometric plan rotation tab
  // "plan" - Original plan tab
  // "carousel" - 2d tab with middle cuts, plan and topView
  "tabs": ["plan", "rotation", "panorama"],

  // Controls in bottom bar, can be:
  // "ruler" - Ruler enable/disable button (panorama tab only)
  // "scale" - Scale x1, x2, x0.5 button (panorama tab only)
  // "autoRotate" - Auto rotate enable/disable button (panorama tab only)
  // "minusScale" - Scale minus button (panorama tab only)
  // "plusScale" - Scale plus button (panorama tab only)
  // "furnished" - Furnished / bareshell button (panorama tab only)
  // "prevPanorama" - Prev panorama button (panorama tab only)
  // "nextPanorama" - Next panorama button (panorama tab only)
  // "2d" - 2D tab button
  // "3d" - 3D tab button
  // "360" - 360 tab button
  // "isometry" - Isometry rotation arrows (rotation tab only)
  // "floors" - Floors select with reverse order inside application frame
  // "carousel" - carousel tab button with plan, top view, middle cuts
  "controls": ["ruler", "scale", "autoRotate"],

  // Enable/disable modal of instruction in 3D tour
  "isInstructionsVisible": true,
  // Enable/disable modal of instruction in ruler
  "isRulerInstructionVisible": true,
  // Show the ruler's instructions only once per session
  "isRulerInstructionShownOnce": false,
  // Enable/disable auto rotation in 3D tour
  "isAutoRotate": false,
  // Enable/disable device gyroscope for AR
  "isGyroscopeEnabled": true,
  // Show/hide fullscreen button
  "isFullscreenButtonVisible": true,
  // Show/hide current room type top label
  "isRoomLabelVisible": false,
  // Show next scale text or current
  // true: next (current: 0.5, shows: 1x)
  // false: current (current: 0.5, shows: 0.5x)
  "isShowNextScaleText": false,
  // Enable InteractiveRotationTab
  // true: InteractiveRotationTab will show on interactive_top_view capability
  // false: always use default RotationTab
  "isInteractiveTabAvailable": true,

  // Use multifloor map instead of default or topView
  "isMultifloorMap": false,
  // Automatic crop transparent part of images by rasterizer (may lag a bit)
  "isNeedCropMultifloorMap": true,
  // Precision of multifloor map crop
  "multiFloorMapCropPrecision": 100,

  // Move panorama control buttons to the application context
  "isAbsolutePanoramaControls": false,
  // Show prev/next room type labels on prev/next panorama buttons
  "isShowLabelsOnPrevNext": true,
  // Render links as div elements in UI layer
  "isOverrideLinks": false,
  // Enable room indexer button in rotation tab
  "isRoomIndexerVisible": false,
  // Enable room indexer button to rotate middle cuts
  "isRoomIndexerRotate": false,
  // Direction of rotation of rooms
  "indexerButtonDirection": false,
  // Show top view on rotation tab
  "isShowTopViewOnRotationTab": true,
  // Show left and right arrows in room scroll container
  "isInteractiveScrollArrowsVisible": true,
  // Show the "hide furniture" button with a separate switch
  "isHiddenFurnitureSwitchVisible": true,

  // Apply scale offset in 2D/3D
  "isTransformScaleWithOffset": true,
  // Apply transform offset in 2D/3D
  "isTransformEnabled": true,
  // Apply scale offset from screen center instead of cursor
  "isTransformAlongScreenCenter": false,
  // Resolve zero angle in middle cuts to rotate from top view more angle-seamlessly
  "isNeedMiddleCutZeroAngle": false,
  // Show VR button (on VR device connected)
  "isVRVisible": true,

  // Rotate the panorama using the left mouse button in any mode
  "isPanoramaLeftMouseRotationOnly": false,

  // Apply a fixed scale that is specified in the scales parameter
  "isFixedScale": false,

  // Inability to scale less than a given value (0.5x / 1x / 2x)
  "minScaleLimit": "0.5x",
  // Inability to scale more than a given value (0.5x / 1x / 2x)
  "maxScaleLimit": "2x",

  // "original" - use original_plan_img
  // "miniplan" - use miniplan_img
  "2DTabBehavior": "miniplan",

  // Base camera persective FOV
  "cameraFov": 75,
  // Custom camera fovs by base FOV Scale
  "cameraFovs": [
    { "text": "1x", "value": 1 },
    { "text": "2x", "value": 0.5 },
    { "text": "4x", "value": 0.25 },
    { "text": "0.5x", "value": 1.35 },
  ],
  // Legacy camera fovs by scale texts (available: x1, x2, x05)
  "scales": ["x1", "x2", "x05"],
  // The size of the links on different scales
  "linkScales": { "x1": 0.1, "x2": 0.1, "x05": 0.1 },
  // Link pulse speed
  "linkPulseSpeed": 0.75,
  // Link pulse amplitude
  "linkPulseAmplitude": 0.08,
  // Link types include regex that should pulse
  "linkPulseTypesIncludeRegex": ".*",
  // Link types exclude regex that should pulse
  "linkPulseTypesExcludeRegex": "door",
  // Link icon include regex that should pulse
  "linkPulseIconsIncludeRegex": "\\w+",
  // Link icon exclude regex that should pulse
  "linkPulseIconsExcludeRegex": "door",
  // Use feet by default
  "isFeetMetric": true,

  // Panorama fade time in seconds
  "panoramaFadeTime": 0.5,

  // Panorama miniplan type, use "svg" or "original"
  "panoramaMiniplanType": "svg",

  // Overrides for interactive opacity
  "interactiveHoverOpacity": 0.65,
  "interactiveActiveOpacity": 0.8,

  // Camera sensitivity
  "cameraHorizontalSensitivity": 1,
  "cameraVerticalSensitivity": 1,
  "mobileCameraHorizontalSensitivity": 2,
  "mobileCameraVerticalSensitivity": 2,

  // Ruler font settings
  "rulerFontSettings": {
    "fontSize": "38px",
    "fontWeight": "Bold",
    "lineHeight": "1",
    "fontFamily": "Roboto Flex",
    "textAlign": "center",
    "borderRadius": 55,
    "scale": 1.5,
    "width": 256,
    "height": 128,
    "textFillColor": "#0008",
    "textHoverColor": "#000f",
    "fillColor": "#fff8",
    "hoverColor": "#fffa",
    "feetsPositionY": 100,
    "feetsPrecision": 2,
    "feetsFormat": "$0 ft",
    "useFeetsComma": true,
    "metersPositionY": 50,
    "metersPrecision": 2,
    "metersFormat": "$0 m",
  },

  // Fallback config
  "assetHostConfig": {
    "version": 1,
    "strategy": {
      "order": ["origin", "group:same", "group:other"],
    },
    "failurePolicy": {
      "http": [403, 404, 410, 429, 451, 500, 502, 503, 504],
      "network": true,
      "cors": true,
      "contentMismatch": true,
    },
    "keyExtraction": {
      "patterns": [
        { "re": "^https?://[^/]+/app_storage_production/public/(.*)$" },
        { "re": "^https?://[^/]+/storage/(.*)$" },
      ],
      "fallback": "pathname-after-first-segment",
    },
    "routes": {
      "cdn-origin.url": {
        "template": "https://cdn-origin.url/{key}",
        "probe": "range",
        "cors": true,
      },
      "cdn2-origin.url": {
        "template": "https://cdn-origin.url/{key}",
        "probe": "head",
        "cors": true,
      },
      // ...
    },
    "groups": {
      "int": [
        "cdn-origin.url",
        // ...
      ],
      "ru": [
        "cdn2-origin.url",
        // ...
      ],
    },
  },

  // Lazy load config
  "lazyLoad": {
    // Is lazy load enabled
    "enabled": true,

    // Strategies (select only one of presented)
    // Nearest cameras on the same floor
    "strategy": {
      "type": "nearest",
      // Preload cameras count
      "count": 3
    },

    // Preload all style on the same floor/camera
    "strategy": {
      "type": "style",
      // Search for another camera with the same position if no same ID
      "usePositionFallback": true
    }
  },

  // Widget external integrations
  "integrations": {
    // https://docs.sentry.io/platforms/javascript/configuration/options/
    "sentry": {
      "dsn": "https://[email protected]/12345"
    }
  },

  // Query parameters for override, only on custom
  "query": {
    "primaryCameraPointId": "CameraPoint123456",
    "primaryFloorNumber": 1,
    "primaryVariantId": "<plan_id>",
    "primaryStyleName": "scandy",
    "primaryFov": 75,
    "primaryTab": "panorama"
  },

  // Custom link icons
  "linkIcons": {
    "door": "https://site.com/door.png",
    "doorHover": "https://site.com/door-hover.png",
    "spot": "https://site.com/spot.png",
    "spotHover": "https://site.com/spot-hover.png",
    "stairUp": "https://site.com/stairUp.png",
    "stairUpHover": "https://site.com/stairUp-hover.png",
    "stairDown": "https://site.com/stairDown.png",
    "stairDownHover": "https://site.com/stairDown-hover.png",
  },

  // Custom UI icons
  "uiIcons": {
    "tabs.2D": "https://site.com/2D.png",
    "tabs.3D": "https://site.com/3D.png",
    "tabs.360": "https://site.com/360.png",
    "tabs.roomIndexer": "https://site.com/roomIndexer.png",
    "room.kidroom": "https://site.com/kidroom.png",
    "room.balcony": "https://site.com/balcony.png",
    "room.gym": "https://site.com/gym.png",
    "room.bathroom": "https://site.com/bathroom.png",
    "room.bedroom": "https://site.com/bedroom.png",
    "room.garage": "https://site.com/garage.png",
    "room.hallway": "https://site.com/hallway.png",
    "room.kitchen": "https://site.com/kitchen.png",
    "room.office": "https://site.com/office.png",
    "room.living": "https://site.com/living.png",
    "room.storage": "https://site.com/storage.png",
    "room.terrace": "https://site.com/terrace.png",
    "room.toilet": "https://site.com/toilet.png",
    "float.close": "https://site.com/close.png",
    "float.extend": "https://site.com/extend.png",
    "float.multiMap": "https://site.com/multiMap.png",
    "float.shrink": "https://site.com/shrink.png",
    "float.fullscreen": "https://site.com/fullscreen.png",
    "instructions.move": "https://site.com/move.png",
    "instructions.research": "https://site.com/research.png",
    "instructions.createPoints": "https://site.com/createPoints.png",
    "instructions.deletePoints": "https://site.com/deletePoints.png",
    "controls.rulerOn": "https://site.com/rulerOn.png",
    "controls.rulerOff": "https://site.com/rulerOff.png",
    "controls.prevPanorama": "https://site.com/prevPanorama.png",
    "controls.nextPanorama": "https://site.com/nextPanorama.png",
    "controls.minusScale": "https://site.com/minusScale.png",
    "controls.plusScale": "https://site.com/plusScale.png",
    "controls.autoRotateOn": "https://site.com/autoRotateOn.png",
    "controls.autoRotateOff": "https://site.com/autoRotateOff.png",
    "controls.arrowLeft": "https://site.com/arrowLeft.png"
  },

  // Overrides locale keys with custom text or translation
  "localeOverrides": {
    "rotate-plan": "Rotate plan",
    "research-plan": "Research plan",
    "create-points": "Create a point",
    "delete-points": "Remove point",
    "instructions-hint-text": "",
    "ok": "Ok",
    "ruler-ok": "Ok",

    "furnished": "Furnished",
    "bareshell": "Bareshell",

    "feets": "Feets",
    "meters": "Meters",

    "made-by-template": "$0 $1",
    "made-by-prefix": "made by",
    "made-by-link": "https://getfloorplan.com/",
    "made-by-text": "getfloorplan.com",

    "style": "Style",

    "floor": "$0 floor",
    "floorNumberEndings": {
      "1": "$0st",
      "2": "$0nd",
      "3": "$0d",
      "rest": "$0th"
    },

    "roomTypes": {
      "KitchenLiving": "KitchLiv",
      // ...
    },
    "fullRoomTypes": {
      "KitchenLiving": "Kitchen Living",
      // ...
    },

    "debugPanel": {
      "header": "Debug Panel",
      "minimizeMaximize": "Minimize/Maximize",
      "planInformation": "Plan information",
      "planID": "Plan ID",
      "serviceID": "Service ID",
      "totalArea": "Total Area (floor)",
      "totalAreaTemplate": "$0 m²",
      "floors": "Floors",
      "rooms": "Rooms (floor / total)",
      "qualityProcessing": "Quality & Processing",
      "rtxQuality": "RTX Quality (panorama)",
      "rtxQualityTopView": "RTX Quality (top view)",
      "processingServer": "Processing Server",
      "primaryVariant": "Primary Variant",
      "variantID": "Variant ID",
      "styleVariants": "Style Variants",
      "navigation": "Navigation",
      "unknown": "Unknown",
      "qualityNames": {
        "-1": "No RTX Preview",
        "0": "Preview",
        "1": "Low",
        "2": "Medium",
        "3": "High",
        "4": "Ultra High",
        "5": "Epic",
        "6": "Unlit"
      },
      "valueNames": {
        "classic": "Classic",
        "proactive": "Proactive",
        "portals": "Portals",
        "mask": "Mask",

        "true": "Enabled",
        "false": "Disabled"
      },
      "capabilityNames": {
        "camera_navigation": "Camera Navigation",
        "floor_navigation": "Floor Navigation",
        "has_panorama": "Has Panorama",
        "hidden_furniture": "Hidden Furniture",
        "interactive_top_view": "Interactive Top View",
        "ruler": "Ruler",
        "top_view_as_miniplan": "Top View Miniplan"
      }
    }
  }
}

Widget object from the REST API

JSON object returned from backend

export default {
  primary_variant: "<id>", // primary variant to open
  variants: [              // all plan variants
    {
      variant_info: {
        style_name: "<name>",          // the name of the variant style
        is_renovation: true,           // is there a renovation in the plan
      },
      plan_id: "<uuid>",               // variant service plan uuid
      json: "<url>",                   // json url for additional plan data
      assets_path: "<path>",           // plan assets base url
      capabilities: { /*...*/ },       // plan capabilities
      rendering_settings: { /*...*/ }, // plan rendering settings

      primary_floor: 0,                // primary plan floor index
      floors: [                        // plan floors
        {
          original_plan_img: "<url>",           // absolute path to original plan image
          miniplan_img: "<url>",                // absolute path to miniplan image

          top_view: {
            image_template: "<template>",       // template for top view decoding
            room_ids_template: "<template>",    // template for top view mask decoding
            items: ["<filename>"],              // top view image names
          },
          isometric_view: {
            image_template: "<template>",       // template for isometric images decoding
            room_ids_template: "<template>",    // template for isometric images masks decoding
            items: ["<filename>"],              // isometric images names
          },
          panorama_view: {
            template: "<template>",             // template for panorama image decoding
            scene_depth_template: "<template>", // template for panorama depth image decoding
            primary_camera_point_id: "<id>",    // primary plan camera id
          },

          location: { X: 0, Y: 0, Z: 0 },        // floor location
          height: 280,                           // floor height

          vertices: [ /*...*/ ],                 // plan vertices data
          rooms: [ /*...*/ ],                    // plan rooms data
          camera_points: [ /*...*/ ],            // plan camera points data
          walls: [ /*...*/ ],                    // plan walls data
          doors: [ /*...*/ ],                    // plan doors data
          stairs: [ /*...*/ ],                   // plan stairs data
          portals: [ /*...*/ ],                  // plan portals data
          apertures: [ /*...*/ ],                // plan apertures data
          decors: [ /*...*/ ],                   // plan decors data

          object_pairs: [],                      // color pairs for furniture data
          room_pairs: [],                        // color pairs for room data
          plan_meta: { /*...*/ },                // plan metadata
        },
      ],
    },
  ],
};

Versioning

For the latest stable version refer to the latest up-to-date version in Quick Start

This project is maintained under the Semantic Versioning guidelines.

However, some versions are being developed for specific clients. We do not recommend using them, as changes in these versions are not documented and may affect your functionality.

Copyright and license

The project code is licensed under the GPLv3 license.

Project code and documentation copyright hart-digital.com. All renders of floor plans copyright getfloorplan.com.