@smarthome.exchange/catalog
🎛️ Web component catalog for the smarthome.exchange product UI.
This package contains the Dees/Lit component layer: design tokens, primitive controls, the landing page, console shell, and console demo components. Its explicitly configured API controller supplies authenticated home state through @smarthome.exchange/api; shared shapes come from @smarthome.exchange/interfaces.
The snapshot/model contract consumes interfaces 2.1.0 and accepts native tcp devices. Hub 3.0 retains the authenticated snapshot and reviewed-approval envelopes. Reported inventory stays inspection-only; write availability requires the hub owner's control-domain selection, adapter permissions and authenticated scopes.
Issue Reporting and Security
For reporting bugs, issues, or security vulnerabilities, please visit community.foss.global/. This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a code.foss.global/ account to submit Pull Requests directly.
Install
pnpm add @smarthome.exchange/catalog
Use The Components
Importing the package registers the custom elements exported by the catalog:
import '@smarthome.exchange/catalog';
document.body.innerHTML = `
<shx-card heading="Living Room">
<shx-badge kind="success" shape="pill">online</shx-badge>
<shx-button kind="primary">Run evening scene</shx-button>
</shx-card>
`;
Render the product surfaces directly:
<shx-landing-page></shx-landing-page>
<shx-console-shell></shx-console-shell>
Public Surface
| Export | Purpose |
|---|---|
shxBaseStyles, shxElementStyles |
Shared design tokens and element base styles. |
shx-badge / ShxBadge |
Status labels with variants, dot mode, and pill shape. |
shx-button / ShxButton |
Product buttons with kind, size, and block layout options. |
shx-card / ShxCard |
Content container with heading, action slot, flush mode, and elevated mode. |
shx-tile / ShxTile |
Console tile container with fill, flush, no-scroll, and action slot support. |
shx-icon / ShxIcon |
Icon wrapper for catalog/product iconography. |
shx-console-icon / ShxConsoleIcon |
Inline icon set used by the console preview components. |
shx-console-shell / ShxConsoleShell |
Console surface for the local home runtime UI. |
shx-landing-page / ShxLandingPage |
Marketing/developer landing page component. |
Console subcomponents are exported for composition and catalog previewing: sidebar, topbar, statusbar, timeline, floor plan, room overview, activity stream, approvals, agent list, quick scenes, and the current view components. shx-console-shell accepts .model, .snapshotResponse, .snapshot, or .provider, in that precedence order. A configured provider shows an unavailable loading state until it returns data; replacing the provider clears its previous home immediately. A standalone shell without any data inputs remains a catalog demo. Snapshot responses use the canonical IReq_GetHomeSnapshot['response'] availability; a raw snapshot has no freshness envelope and is therefore rendered as stale and non-live. Snapshot device ownership is shown only when metadata.ownerId identifies a known agent; missing or unknown ownership remains explicit in the UI.
Live Now renders shx-console-room-overview from reported rooms and device assignments. It preserves room IDs and floors, includes rooms without devices, and identifies unreported room IDs and unassigned devices. Each room shows reported connectivity counts and device states. Its “Inspect room map” disclosure supplies those same rooms and devices to shx-console-floor-plan, grouped by reported floor. Geometry and room occupancy are unavailable in the snapshot contract. The expanded room map uses natural height inside the Rooms tile, so its room and device details share that tile's scrolling. Supplied timelines have a keyboard-focusable panel with explicit full-day and all-agent scrolling guidance.
Insights renders device connectivity, enabled-agent and pending-approval counts from the supplied model. For snapshots, its audit count and activity data cover every returned receipt. The mapper preserves the original receipt timestamps, kinds, home and verified subject IDs, caller attribution, tool and approval identifiers, action digests, execution IDs, scopes and summaries, without inferring an execution outcome. It shows the snapshot capture time, canonical freshness and the oldest/newest returned receipt timestamps; it does not imply a complete daily or historical reporting window. Custom models can supply optional home.rooms, device roomId and insights fields. Without receipt metadata, Insights shows the supplied activity-entry count and explains which timestamps are unavailable. An unavailable provider renders an explicit unavailable state.
Agents
shx-console-agents-view accepts .agents, .source, .availability, .loadState, .statusMessage and .capturedAt. Search matches names, IDs, roles and configured scopes; the mode filter narrows the roster. Inspecting an agent shows its identity, role, enabled state, configured mode and scopes, and reported action count, running tools and latest activity. Missing status stays unreported, including the distinction between a reported zero and an absent action count. Online health, effective access grants and automation runs are explicitly unreported because the current input contract does not expose them. These controls provide read-only inspection.
The view and shx-console-agent-list default to empty input. Their static catalog demos opt into demo agents explicitly. The list can opt into .selectable and .selectedAgentId; its shx-agent-selection event carries a frozen { agentId } detail and bubbles across shadow boundaries. Selection does not emit a runtime action. Optional agent configuredScopes and status preserve the snapshot's structured scopes and telemetry. Custom console models can set loadState to ready, loading, error or unauthorized, with a safe contextual statusMessage. For each non-ready state, the shell clears retained home, device, agent and audit display inputs while preserving the selected view; ready models retain their supplied data. This display behavior does not enforce authorization. The shell classifies provider loading and general failures directly, and never infers authorization failure from arbitrary error text.
Approval buttons emit shx-approval-decision with frozen { approvalId, expectedActionDigest, decision }, and navigation emits shx-view-change with { view }. The same interactions, plus all other console controls, emit the discriminated shx-console-action event. Its action is add-block, approval-decision, ask-assistant, navigate, new-rule, notifications, open-settings, refresh-activity, or run-scene; navigation, approval, and scene actions include their ID as targetId, and approval actions also include expectedActionDigest and decision. All three events bubble and cross shadow boundaries (bubbles: true, composed: true) so host applications can connect them to runtime APIs. Quick scenes, savings, latency and energy-history charts remain demo-backed until dedicated runtime contracts exist. Timeline and schedule can render explicitly supplied view models as described below; the current snapshot API does not supply those models. The shell only mounts those demo surfaces for its explicit demo model, so fabricated demo IDs cannot be invoked from snapshot or custom shells.
Approval review
Snapshot mapping retains each pending approval's original immutable action and exact server-supplied digest as .review: IShxConsoleApprovalReview. The mapper makes an independent, deeply frozen copy. The disclosure shows the bound home, verified requester kind and ID, tool and revision, required scopes, plan/call identifiers, attributed caller, complete input and digest. Decisions become available inside that opened review. A refresh that changes the digest closes its prior review.
Both approval events carry the digest captured from the rendered review, even if the supplied record changes before handling a click. A host forwards that exact expectedActionDigest to submitApproval; it must never obtain a replacement digest from a refreshed approval list. The hub owns current authorization, canonical digest verification and exactly-once dispatch. The catalog validates display input and never computes or authenticates a digest.
Custom approval models may omit .review for read-only summaries. They cannot emit decision events. Migrating a host from the older { approvalId, decision } event requires the original action and server digest in each actionable model and forwarding the new field. Standalone approval lists default to empty; their previews supply static summaries explicitly.
Standalone approval lists accept .loadState and .statusMessage. Loading, error and unauthorized states hide actions and distinguish unavailable data from a ready empty queue. The bound Now view forwards that state and shows an unknown pending count until ready. Removing a focused action moves focus to a safe summary or a persistent status; an unchanged empty poll preserves that focus, and returned actions restore a summary for fresh review. Removal wording describes availability in the view without inferring the server's pending or execution state.
Additional demo data exports are available for catalog previews, including agents, devices, approvals, household data, rooms, blocks, and activity stream examples.
Activity
shx-console-activity-view accepts .activity, .approvals, .summary, .source, .availability, .loadState (ready, loading, error, or unauthorized) and .statusMessage. The reusable shx-console-activity-stream accepts .events and the same source, availability and load-state properties. A standalone Activity view or stream starts empty; its catalog demo explicitly supplies demo records. Loading, unavailable, error and unauthorized states hide record and approval controls. Refresh emits the existing shx-console-action event with { action: 'refresh-activity' }; the host owns authenticated fetching.
Activity searches supplied actor, record, tool and summary values and filters exact source kinds and explicitly supplied outcomes locally. It reports shown and supplied counts without implying complete history. Complete createdAt timestamps order records newest first, with the record ID resolving ties. If any full timestamp is missing, the supplied order is retained, including after filtering. Each keyboard-accessible record disclosure distinguishes the verified subject from attributed caller and shows the supplied home, action digest and execution IDs alongside input and output summaries, the full timestamp and reversibility. Receipts do not currently carry execution outcomes; Activity therefore shows Not reported and never infers success from receipt text. Hosts supplying typed IShxConsoleActivityEntry records can provide explicit execution or approval outcomes, including pending, failed and indeterminate states. A reported execution does not verify the physical device effect.
Devices
shx-console-devices-view inspects the supplied inventory with search and composing room, integration, connectivity and capability filters. Snapshot mapping retains reported integrationDomain, protocol, unique capabilities and the newest valid state timestamp as optional device updatedAt. Missing metadata stays explicit and can be filtered as unreported; connectivity is not a device-health guarantee. Expanding a row shows its reported state, identifiers, ownership and latest observation time in UTC. Snapshot capture time and device observation time describe different observations.
The component defaults to an empty, unavailable inventory. Supply .devices, .source, .availability, .loadState, .statusMessage and optional .capturedAt for standalone use; the shell binds its current model. Its static catalog demo explicitly opts into demo inventory. Loading, failed, unauthorized and unavailable states hide the prior inventory. Stale inventory remains inspectable with an explicit warning. An empty inventory and filters with no matches have separate messages.
Opening details emits the typed shx-device-select event with { deviceId }, bubbling across shadow boundaries. This is a local inspection event; it does not invoke a tool, change state or grant access. Device capability and ownership metadata do not establish permission to operate a device.
Timeline and schedule
shx-console-timeline and shx-console-schedule-view accept a supplied
.model: IShxConsoleTimelineModel. The same input drives the daily agent lanes
and Monday–Sunday schedule:
const timeline = document.createElement('shx-console-timeline');
timeline.model = {
homeId: 'home-a',
timezone: 'Europe/Berlin',
referenceTime: '2026-10-06T09:00:00Z',
agents: [{
id: 'comfort', name: 'Comfort', initials: 'CO',
color: '#f59e0b', mode: 'auto',
}],
entries: [{
id: 'morning-light', agentId: 'comfort', title: 'Morning light',
startsAt: '2026-10-06T07:00:00Z', endsAt: '2026-10-06T09:00:00Z',
status: 'done',
}],
};
document.body.append(timeline);
Entries have unique IDs, known agent IDs, absolute RFC3339 start/end timestamps,
and a status of done, running, scheduled, needs-approval, or proposed.
An optional reason appears with the full action details. The input guard
isShxConsoleTimelineModel rejects invalid dates, time zones, duplicate IDs,
unknown agents, and reversed intervals. Invalid supplied data never becomes a
demo schedule.
Both views support date navigation and combined agent/status filters. They order
actions by start, end, then ID without changing the input. The timeline gives
overlaps separate tracks and clips overnight actions to the visible day while
retaining their complete timestamps. Time labels include the UTC offset; day
placement follows elapsed time across 23-hour and 25-hour clock changes. The
highlighted day and reference marker come from referenceTime, independently
of the browser's clock or time zone. Same-home updates preserve filters;
switching homes resets them.
Set .loading = true or a user-facing .error message to show the corresponding
state. Missing input and an empty supplied schedule are distinct. Standalone
views default to missing input. Catalog previews opt in with demo-data; a
supplied model takes precedence. Only the explicit schedule preview emits the
new-rule action. Supplied schedules are read-only.
The published snapshot contract has no schedule data. Host applications supply these view models explicitly; audit receipts are not inferred to be planned actions.
Floor Plan
shx-console-floor-plan displays a room map from .rooms and .devices, grouped by the rooms' reported floors. The current room contract has no geometry or occupancy, so the component says so instead of drawing a guessed house. Same-named rooms remain separate by roomId; missing room records and unassigned devices have their own groups. Empty reported rooms remain visible.
Supply .homeId to reset inspection when switching homes and .availability (live, stale, demo, or unavailable) to label the source. .loading and .errorMessage distinguish a pending request from failed, unavailable, and empty data. Defaults contain no demo rooms or devices; the catalog's static demo binds its data explicitly.
Room and device selectors are keyboard-accessible native buttons with visible focus, room pressed states, and device expansion states. Escape closes device details while retaining the selector's focus. Selected-device details show only the supplied ID, connectivity, state, value, and owner. Inspection emits no tool commands or approval events. The component fits narrow catalog containers; the host owns snapshot loading and authenticated API calls.
Authenticated host integration
ShxConsoleApiController consumes the published authenticated API 1.0 client and the current home snapshot mapper. Configure the selected home and an operator-supplied asynchronous Authorization header provider explicitly. Credentials stay in the host's provider and HTTP headers; the catalog neither signs in nor persists them.
import {
ShxConsoleApiController,
ShxConsoleShell,
type IShxConsoleApiControllerOptions,
} from '@smarthome.exchange/catalog';
export function mountHomeConsole(
container: HTMLElement,
options: IShxConsoleApiControllerOptions
) {
const shell = new ShxConsoleShell();
const controller = new ShxConsoleApiController(options);
const detachAndClose = controller.bind(shell);
container.append(shell);
return {
shell,
controller,
cleanup: async () => {
await detachAndClose();
shell.remove();
},
};
}
// Retain this handle before startup so failed startup can still be closed.
const mounted = mountHomeConsole(document.body, operatorConfiguredOptions);
await mounted.controller.start();
// await mounted.controller.refresh();
// await mounted.cleanup();
operatorConfiguredOptions supplies required homeId and authorizationHeaderProvider, plus optional hubUrl, pollIntervalMs (default 5000) and requestTimeoutMs (default 10000). The API client validates the absolute HTTP(S) hub URL and immutable home binding. Controller options accept only supported own data properties. The header provider receives the API's current HTTP operation, endpoint, home and cancellation signal. It should cooperate with cancellation for its own resource cleanup. The HTTP deadline starts after credential preparation; it does not impose a deadline on a foreign credential service.
bind(shell) attaches display and action listeners and applies an unavailable model; it does not fetch or start a socket. start() explicitly fetches and starts the API client's snapshot polling. refresh() pauses and drains an older poll before obtaining a new uncached snapshot, then resumes the owning watcher. provider also exposes the existing typed provider seam for one-shot host composition; ongoing display updates use bind() or subscribe(). subscribe(listener) immediately supplies the current frozen display model and returns an idempotent unsubscribe function; listeners are synchronous. model, homeId and isClosed are public readonly views.
The controller exclusively owns its bound shell until cleanup succeeds. Its async binding cleanup detaches listeners and calls terminal close(). Close immediately clears home data, cancels pending credentials and HTTP work, stops/drains the published watcher and admitted requests, and prevents later results from restoring a home. A failed owned stop remains available for a later explicit close/cleanup retry. Retain a failed cleanup handle and finish it before binding another home; startup and refresh remain unavailable after terminal close. Repeating an old successful cleanup never clears a later home's display.
Successful responses must pass the current snapshot display guard and match the exact selected home. Invalid, foreign-home and failed responses clear prior home, device, approval and audit data and show a safe error state. The controller does not infer an authentication failure from error text or publish response/provider error details. The display checks require interfaces 2.1.0 approval actions, requester kinds and matching receipt/dashboard homes, and preserve TCP/UDP metadata. They do not establish authorization; the hub verifies current identity, grants, scopes, digests and dispatch.
The binding forwards shx-approval-decision directly through submitApproval() with its exact rendered expectedActionDigest, shows a submitting/loading state and refreshes authoritative data afterward. It never obtains a replacement digest from a newer model. The matching general shx-console-action event does not submit a second decision. refresh-activity triggers authenticated refresh; unsupported product intents remain host events. An aborted or closed HTTP approval request does not establish whether an already admitted device action completed; inspect its durable approval/audit state before another attempt.
Browsers use the published client's authenticated HTTP methods and watcher. The controller never calls its Node socket startup, creates a cookie-ticket endpoint, sends credentials in RPC or supplies an authentication fallback. Cross-origin HTTP requires the host's server/CORS policy. Runtime hosts should mount createShxConsoleErrorModel('Select an authorized home') before explicit configuration; an unconfigured catalog preview remains an explicit demo. Timeline and schedule still require separate host view models because the snapshot contract supplies no schedule data.
Primitive Attributes
| Element | Useful attributes and slots |
|---|---|
shx-badge |
kind, dot, shape="pill". |
shx-button |
kind, size, block. |
shx-card |
heading, flush, elevated, slot="action". |
shx-tile |
heading, fill, flush, no-scroll, elevated, slot="action". |
Development Preview
The html/ entry wires the catalog into @design.estate/dees-wcctools so components can be previewed locally by the surrounding build/watch tooling.
pnpm build
pnpm watch
pnpm test
pnpm test builds the package and runs its focused browser tests.
Development pins @git.zone/tsbuild to 6.0.0-beta.0, which compiles with TypeScript 7.1. Use the declared pnpm 12.8.1 version when installing or updating the lockfile. Production bundles include the third-party notices emitted by @git.zone/tsbundle beside dist_bundle/bundle.js.
Design Notes
- Public components use
@design.estate/dees-element; the HTML development catalog usesdees-domtoolsand the dev-onlydees-wcctoolsentry. - Components are registered as custom elements and can be used from plain HTML, TypeScript, or higher-level app shells.
- Demo data is for catalog previews. Durable domain types belong in
@smarthome.exchange/interfaces.
License and Legal Information
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the LICENSE file.
Please note: The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
Trademarks
This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.
Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.
Company Information
Task Venture Capital GmbH
Registered at District Court Bremen HRB 35230 HB, Germany
For any legal inquiries or further information, please contact us via email at hello@task.vc.
By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.