@glidevvr/unit-table
v0.14.22
Published
`@glidevvr/unit-table` is a React and TypeScript-based npm package designed to display and manage facility unit data with dynamic filtering and configuration.
Readme
Overview
@glidevvr/unit-table is a React and TypeScript-based npm package designed to display and manage facility unit data with dynamic filtering and configuration.
Installation
npm install @glidevvr/unit-tablePeer dependencies: React 19 and React DOM 19 are required.
Usage
import { UnitTable } from "@glidevvr/unit-table";
import "@glidevvr/unit-table/style.css";
<UnitTable
apiKey="YOUR_API_KEY"
options={{
facilityIds: [1234],
// ...additional options (see Configuration Options below)
}}
/>Local Development
Follow these steps to run and test Unit Table locally:
- Run
npm run start- Append
:prodor:devor:qato denote which se api you want to connect to. Default is prod.
- Append
- cmd click on the url outputted.
Prerequisites
- Node.js version: 20.x or later
- NPM version: 10.x or later
Stack
Unit Table uses the following technologies:
- React: JavaScript library for building user interfaces.
- TypeScript: Provides type safety and improves code maintainability.
- Vite: A fast build tool with hot module replacement.
- Shadcn: Component library for consistent UI elements.
- Tailwind CSS: Utility-first CSS framework for custom styling.
- Vitest: Testing framework for fast and reliable tests.
Branching Strategy
Unit Table follows a Dirty Trunk repo structure to enable fast, continuous integration.
Trunk (Main Branch)
masteris the trunk where all development merges.- Trunk may contain work-in-progress code and is not guaranteed to be in a release-ready state at all times.
Feature Branches
- Use short-lived branches for features or fixes:
- Naming convention:
feature/<feature-name>orbugfix/<issue-description>.
- Naming convention:
- Merge into
masterfrequently to avoid long-lived branches and reduce conflicts. - Use squash merges to keep the history clean.
Release Branches
- Create
release/x.y.zbranches frommasterwhen ready to stabilize for a release. - Only bug fixes and release preparation changes go into the release branch.
- After release, merge back into
masterand tag with the version.
Hotfixes
- Create
hotfix/x.y.zbranches from the latest tagged release. - Merge back into
masterand the active release branch.
Managing CI/CD
Unit Table uses Bitbucket Pipelines for testing, linting, and publishing:
- Branch Tests: Automated build, linting, and testing run on all branches (
feature,bugfix,release,hotfix). - Publishing: npm releases are triggered manually via the
npm-publishcustom pipeline in Bitbucket. - Versioning: Uses semantic versioning:
- Increment minor versions on releases.
- Increment patch versions for hotfixes.
Running Tests
- To run tests, use:
npm test - For coverage:
npm test --coverage
Contributing
- Create a feature branch.
- Ensure all tests pass before submitting a pull request.
- Follow the project’s coding standards and linting rules.
Configuration Options
Unit Table's behavior can be customized via the options object:
options: {
facilityIds: [], // Array of SE Facility Ids REQUIRED
tableLayout: "row", // "grid" | "row"
buttonLayout: "combined", // "combined" | "separate"
disableRental: false, // boolean
disableReservation: false, // boolean
disableSoftReservation: false, // boolean
allowedCategories: "", // String of categories to filter by name, comma separated
allowedFeatures: "", // String of features to filter by name, comma separated
categoryOrder: [], // Array of category slugs (Layout 2 only). Listed categories render first in this order; unlisted ones fall back to the default order. Layout 1 keeps API order.
sort: "", // String of sort.
vacancyNotice: true, // boolean, Enables vacancy notice display
vacancyThreshold: 3, // number, Minimum number of units left to trigger a vacancy notice
unavailableUnits: false, // boolean, Show unavailable units on the table
groupBy: "", // Define how units from the api should be grouped
rentalApp: {
location: "dialog", // "drawer" | "external" | "dialog" Location of the rental app
externalUrl: "", // Url for the external rental app
},
reservationApp: {
location: "dialog", // "drawer" | "external" | "dialog" Location of the reservation app
externalUrl: "", // Url for the external reservation app
},
softReservationApp: {
location: "drawer", // "drawer" | "external" | "dialog" Location of the reservation app
externalUrl: "", // Url for the external soft reservation app
},
additionalUnitSourceInfo: "", // Comma separated list of vendor source data keys. Mainly for use in the external app urls.
showAppliedPromoPrice: true, // boolean, Displays price with promotions applied
language: {
grid: {
strikeThroughRate: "Starting at"; // String | Text (Starting at) for strike through
webRate: "Web Rate"; // String | Text for 'Web Rate'
promoRate: "Promo Rate"; // String | Text for "Promo Rate"
},
action: {
reserveButton: "Reserve"; // String | Text for "Reserve" action button
rentButton: "Rent"; // String | Text for "Rent" action button
selectButton: "Select"; // String | Text for "Select" action button. Select typically will open a journey for either VBP or Rent/Reserve/Quote selection.
quoteButton: "Get a Quote"; // String | Text for "Quote" action button
}
},
valueBasedPricingSettings: {
tierA: {
label: "Standard", // String | Title of the Tier A
description: "", // String | Description of the Tier A
},
tierB: {
label: "Best Value", // String | Title of the Tier B
description: "", // String | Description of the Tier B
},
tierC: {
label: "Deluxe", // String | Title of the Tier C
description: "", // String | Description of the Tier C
},
tierOrder: ["tierA", "tierB", "tierC"], // Array of Strings | Order from left to right that the tiers should appear in the modal.
}
}External Rental App / External Reservation App / External Soft Reservation App
You can pass in a url and if you need values mapped to the url pass them in using the dot notation and the app will "translate".
unitTableOptions: {
facilityIds: [6011],
rentalApp: {
location: "external",
externalUrl: "https://compass-rental.ssm-erp.com/home/{{facility.vendor_id}}/{{unitGroup.representative_unit.source.UnitTypeId}}/{{unitGroup.representative_unit.vendor_id}}/en/{{unitGroup.rates.promo_rates.0.vendor_id}}/null"
},
additionalUnitSourceInfo: "UnitTypeId"
}If you are accessing additionalUnitSourceInfo then you just need to do unitGroup.representative_unit.source.{key goes here}. No need to do any array indexing, the translate process accounts for the additional source key value format.
Data Sources
The Unit Table uses the SE API Wrapper package to interface with the Storage Essentials Api. This also means it makes use of RTK Query to take and manage the received data.
The Unit Table hits the following endpoints for its data:
- getUnitGroups
- getFacilitiesV2
Changelog
[0.14.22] - 2026-07-16
Changed
- Mobile (all layouts, ≤767px): the featured-unit Badge now sits on the left edge of the image (vertically centered, overhanging), matching the Layout 2 grid position (WEB-1508). On mobile the promo banner sits across the top of the stacked card, so the previous top-right/corner placement collided with it.
[0.14.21] - 2026-07-15
Changed
- Split the Layout 2 featured-unit Badge position by display mode (WEB-1508):
- Row: top-right corner of the unit image, with the per-shape wide/tall lifts (0.14.18 behavior). The promo-banner collision is handled on the theme side by relocating the promo banner above the action buttons.
- Grid: left edge of the image, vertically centered and overhanging outward (the 0.14.19 position), to clear the promo banner that spans the top of the grid card.
[0.14.20] - 2026-07-15
Changed
- Advanced market table now hides units that would only show "Call for Availability" — click-to-call unit types, or otherwise non-transactable units at facilities whose quote type is "call" — since they can't be rented or reserved from the market page. "Get a Quote" (soft-reservation) lead units still show, and facility pages are unaffected (the filter is gated on market mode). (WEB-704)
[0.14.19] - 2026-07-15
Changed
- Featured-unit Badge on facility Layout 2 now sits on the left edge of the unit image, vertically centered and overhanging outward, instead of the top-right corner (WEB-1508). This clears the top of the card where a promo banner (e.g. "FREE 1 Month's Rent") can sit and previously collided with the badge. Layout 1 / market placement (top-right) is unchanged.
[0.14.18] - 2026-07-14
Added
- Badge treatment for featured units-table rows (WEB-1508): a colored, text-labeled promotional badge (e.g. "Flash Sale") overlaid on the unit image, as Option 2 alongside the Tab row highlight. Editors pick one of 12 shapes + any color + text in the CMS. The label auto-scales to fit each shape (per-shape placement, size, rotation, and line caps; whole-word wrapping, no truncation), text contrast is WCAG-derived, and badge rows pin to the top when the CMS pin-to-top toggle is on. Rendered top-right of the unit image on both layouts (lifted/smaller on Layout 2).
[0.14.17] - 2026-07-13
Changed
- Market template now shows the 3 cheapest units per facility (by displayed rate, any size), rows ordered cheapest-first — replacing the previous one-row-per-size selection. (WEB-704)
Performance
- Market facility cards lazy-mount their unit rows: only facilities in or near the viewport hydrate their rows (Rent/Reserve buttons, promo dropdowns, tooltips); the rest mount on scroll via an IntersectionObserver. Reduces initial hydration/DOM on large market pages (20-50+ facilities). (WEB-704)
[0.14.16] - 2026-07-10
Added
- Advanced market units table ("market" mode) for the market page: each facility renders as a card — banner image, name, address, reviews, first-3 feature pills, and a "See All Units" link — wrapping that facility's live unit rows with working Rent/Reserve journeys, promos, and urgency messaging. A matching loading skeleton reuses the facility-card layout (real header + skeleton unit rows) instead of a flat list of generic rows. New
FacilitySection,ReviewsRow,StarRating, andgroupByFacilitybuilding blocks. (WEB-704)
[0.14.15] - 2026-06-29
Fixed
- Removed the no-op back (✕) button that rendered above the inline Reserve/Get a Quote form on Layout 1 multi-promo units. Layout 1 picks the promo on the card's "Choose Your Special" dropdown rather than a separate selector step, so there was nothing to navigate back to; the Layout 2 multi-promo back button is unchanged. (WEB-1502)
[0.14.14] - 2026-06-25
Added
- Inline "Get a Quote" and "Reserve" expansion in Layout 1 grid view: either action now opens a full-width panel that pushes the cards below it down (matching Layout 2 and the nearby panel) instead of expanding inside the individual card. The panel is form-only — it submits the promo chosen in the card's "Choose Your Special" dropdown, with no separate in-expansion promo selector. (WEB-1432)
Changed
- Bumped
@glidevvr/reservation-appto 0.4.4 — each inline form instance now gets its own store, so a remounted form (close → reopen, or opening another unit) no longer inherits the previous instance's stale state. Fixes the email/SMS opt-in toggles freezing after the first mount. (WEB-1529)
Fixed
- VBP units with separate Rent/Reserve buttons now open the value-based-pricing modal (or the inline form, per the facility setting) instead of navigating straight to the reserve page. (WEB-1432)
- A reserve form taller than the viewport keeps its top in view when it expands, instead of jumping the scroll to the bottom of the form. (WEB-1432)
- Layout 1 grid cards no longer squish at mobile widths — a card in a single-column grid now spans the full width rather than using the multi-column placement. (WEB-1432)
- An open quote/reserve expansion closes automatically if its unit is filtered or sorted out of the list, so stale expansion state can't linger. (WEB-1432)
[0.14.13] - 2026-06-22
Added
- Nearby Units in grid view (previously row-only). Layout 2 grid renders the panel as a full-width push-down expansion below the card's row (matching the promo expansion); Layout 1 grid renders a full-width sibling at 2 columns and a card-anchored overlay (no card reflow) at 3-4 columns, chosen by the grid column count. New
NearbyPanel,FindNearbyButton, andGridNearbyExpansioncomponents. (WEB-407) - Reviews on the nearby facility cards, rendered from
facilityMap[id].reviewsScore/reviewsCountwhen present. (WEB-407)
Changed
- The nearby panel's facility cards and map reflow via container queries — responding to the panel's own width rather than the viewport — so cards sit beside the map only once the panel is wide enough and otherwise stack. (WEB-407)
Fixed
- "Get a Quote" on sold-out rows was a no-op (the unavailable-unit row stubbed the in-row promo-expansion state); it now opens the inline quote form. (WEB-407)
- Only one in-row expansion is open per row — opening Find Nearby closes the quote form and vice versa. (WEB-407)
- The Find Nearby close icon is absolutely positioned beside the label, so toggling it no longer widens the button or shifts the surrounding cards. (WEB-407)
[0.14.12] - 2026-06-18
Fixed
- Promo dropdown box now expands to contain its text instead of overflowing the box. (WEB-1517)
- Feature and category filter options are only shown when an available unit group has them, so amenities/categories that exist only on sold-out units no longer appear as filters. (WEB-1518)
[0.14.11] - 2026-06-15
Added
- Featured unit-group rows via the
featuredUnitsoption (max 2). Configured groups are matched locally against the loaded unit list (byrepresentative_unit.id, string-coerced) and given a "Tab" visual treatment: a colored outline, a background tint, and a vertical tab ribbon with a label, all driven by the CMS-selectedcolor. Optional host-providedcolorLight(row tint) andcolorForeground(ADA-correct text) are used when present, falling back to a CSScolor-mixand the widget's own luminance-based text color. Applied in both row (UnitItem) and grid (GridPromoExpansion) layouts; thebadgetreatment is reserved for a later task. (WEB-1502) pinFeaturedToTopoption (CMS toggle, defaults tofalse). When on, featured groups are pinned to the top via a stable partition applied after sorting, preserving the relative order within both the featured and non-featured sets. (WEB-1502)- "Featured units" filter in the filters and More Filters modals, shown only when featured groups are configured. Wired into the applied-filter count, Clear All, and Apply, backed by new
selectedFeaturedfilter state. (WEB-1502)
Changed
getTextColorForBackgroundnow uses the gamma-corrected WCAG 2.0 relative-luminance formula (mirrors the host repos'getContrastTextColor), adds an exportedgetLuminance, normalizes#abcshorthand hex, and falls back to white text for unparseable input. (WEB-1502)- Strip the client-side
featuredsort token from the Storage Essentials API sort params — it is handled client-side via pinning and is not a valid SE sort property. (WEB-1502)
[0.14.9] - 2026-06-05
Fixed
InlineReservationForm hardcoded the Reservation environment from import.meta.env.VITE_SE_ENVIRONMENT (baked into the published bundle → production), so the inline quote/reserve form POSTed to the production SE API even on staging. Read state.apiKey.environment from Redux instead — the same host-provided source the widget's own data calls use.
[0.14.8] - 2026-06-03
Added
- Configurable category ordering for Layout 2 via the
categoryOrderoption. Listed category slugs render first in the given order; unlisted categories fall back to the default order (size by area ascending, then unit-type A→Z). Layout 1 keeps the API order. (WEB-1474) - Inline Get a Quote and reserve/booking forms in the expanded Layout 2 row, hosted by the mode-aware
InlineReservationForm. Multi-promo units use a stepped flow: the promo selector advances to the in-row form (carrying the chosen promo) with a back control, while single/no-promo actions open the form directly. The selector shows a single context-aware Continue matching the inline button that opened it (Rent/Reserve/Quote/Select), with the heading prefixed by the action. Wired in both row (UnitItem) and grid (GridPromoExpansion) layouts; underlying funnel actions and tracking are unchanged. Separate-layout multi-subgroup (VBP) units still navigate to the funnel rather than reserving the representative unit inline. (WEB-1436)
Fixed
- Gate the quote/call slot on the facility query resolving instead of its loading state, so "Call for Availability" no longer flashes before "Get a Quote" on sold-out RESERVE units. Action loading skeletons are now full-width pills matching the action buttons, rendering 1 or 2 based on button layout. (WEB-1436)
Update
- update reservation-app to 0.4.2 (WEB-1436)
[0.14.7] - 2026-05-27
Fixed
- Adding the "View More" button dropdown toggle on mobile when there are more than 2 amenities
[0.14.6] - 2026-05-26
Fixed
- Isolate Redux store per
UnitTablemount so multiple unit tables on the same page no longer share journey/filter state (WEB-1481)
[0.14.5] - 2026-05-18
Update
- update reservation-app to 0.4.1 (WEB-1476)
[0.14.4] - 2026-05-11
Update
- Use
ReservationType.SOFTfor QUOTE funnel type inUnitFunnelso soft reservations are created when generating quotes (WEB-1270)
[0.14.3] - 2026-05-06
Update
- Uncomment
leadModeprop on the reservation funnel inUnitFunnelso QUOTE funnel type enables lead mode
[0.14.2] - 2026-05-04
Update
- update reservation app to 0.4.0
[0.14.1] - 2026-04-27
Update
- use @glidevvr/reservation-app instead of @glidevvr/cirrus
[0.14.0] - 2026-04-27
Fixed
- Revert combined rent/reserved VBP buttons to remain separate when Separate buttons is selected.
[0.13.0] - 2026-04-22
Fixed
- Null-safe access to
facility.settingsinJourneyContent,QuoteButton,TriggerButtons,SkeletonUnitItem, anduseTriggerButtonVisibilityto prevent runtime errors whensettingsis missing - Flaky
TriggerButtonsseparate-layout test by pinningsub_groupsto an empty array
Changed
useRentalAction.openRentalFunnelnow accepts an optionalselectedUnitIdand threads it throughredirectToExternalRentalandopenSamePageRentalFunnel, falling back to the hook'sunitIdwhen not provided
[0.12.0] - 2026-04-07
Added
- Layout 2 grid card view with responsive column layout (1/2/3 columns by breakpoint)
- Grid promo expansion as full-width sibling card with animated expand/collapse transitions
- "Close" button replaces Rent/Reserve/Select when promo panel is expanded (Layout 2 multi-promo)
closeButtonlanguage option for customizing the Close button label- Smooth scroll-into-view for grid promo expansion in modals and overflow-x:hidden containers
Changed
- Single action buttons (Rent-only, Reserve-only, Select) now render in the Reserve (bottom) position on grid cards for consistent alignment
- Scroll-into-view uses ease-in-out-cubic easing and detects nearest scrollable ancestor instead of always targeting window
Removed
- X icon overlay on expanded Rent/Reserve/Select buttons (replaced by Close button)
[0.11.0] - 2026-04-06
Update
- Update the Cirrus version to latest:1.11.2
[0.10.0] - 2026-03-30
Added
- Layout 2 multi-promo expandable rows with radio button promo selection
- "More Amenities" tooltip for Layout 2 units with 3+ features
- "SALE" ribbon for multi-promo units in Layout 2 (replaces Select dropdown)
- VBP Select button now shows for VBP units even in Separate button layout
- "Select Now" button in expanded promo row for VBP units (opens VBP modal)
- Accessibility: aria-expanded, aria-controls, role="radiogroup" on expand/collapse elements
Fixed
- Reserve button aria-controls now always references the promo panel when expandable
[0.9.0] - 2026-03-25
- Add support for layout 2 and pill filters
[0.8.1] - 2026-03-25
Fixed
- Pass unit id correctly in VBP tiers to Reservation funnel
[0.8.0] - 2026-03-24
Added
- environment option for api calls
