Skip to content

Releases: ha-china/html-card-pro

TailwindCSS

Choose a tag to compare

@knoop7 knoop7 released this 06 Jun 17:39

Skeleton Loading Layer

  • Added soft and consistent skeleton effects during card pre-render and render phases to reduce jarring layout jumps
  • Preview area now uses a controlled skeleton layer to prevent the "single horizontal line" collapse issue before content loads
  • Lightweight overlay added for quick re-renders to make brief refreshes feel smoother

Graceful Image Fallback

  • Missing or failed images now display a clean light gray visual placeholder instead of leaving broken gaps

YAML Entity List Recognition

  • When pasting complete YAML configurations into the editor, entity arrays are now recognized more reliably and preserved in the config state

External Script Library Support

  • Added support for importing external script libraries including Tailwind CSS (twcss), Bootstrap JS Bundle, anime.js, and other utility frameworks
  • Skeleton placeholders are shown while scripts load, then smoothly transition to rendered content once ready to prevent style flashing
  • Key online JS library URL: https://cdn.tailwindcss.com
  • Usage: Add a scripts field to the card configuration with the external script URLs. The system loads them in order during initialization and keeps the skeleton state active until all resources are ready.
type: custom:html-pro-card
scripts:
  - https://cdn.tailwindcss.com
content: |
  <div class="bg-blue-500 text-white p-4 rounded-lg shadow-md">
    <h1 class="text-xl font-bold">Hello Tailwind</h1>
    <p class="mt-2">This card is powered by Tailwind CSS utility classes.</p>
  </div>

Full Changelog: v3.7...v3.8

Claw!

Choose a tag to compare

@knoop7 knoop7 released this 29 May 08:20

  ┌────────────┐      ┌────────────┐      ┌────────────┐
  │ HTML Card  │─────▶│  claw API  │─────▶│    Home    │
  │  Content   │      │  Runtime   │      │ Assistant  │
  └────────────┘      └─────┬──────┘      └────────────┘
                            │
        ┌───────────────────┼───────────────────┐
        ▼                   ▼                   ▼
  ┌──────────┐        ┌──────────┐        ┌──────────┐
  │  claw.*  │        │ claw.ws  │        │ claw.api │
  │  state   │        │  send    │        │   get    │
  │  toggle  │        │  call    │        │   post   │
  └──────────┘        └──────────┘        └──────────┘
        │                   │                   │
        └───────────────────┴───────────────────┘
                            │
  ┌─────────────────────────┴─────────────────────────┐
  │              DOMAIN-SPECIFIC APIs                 │
  ├──────────┬──────────┬──────────┬──────────┬───────┤
  │ .config  │ .areas   │ .devices │.entities │.scenes│
  │ .scripts │.automations│.lovelace│ .system │.users │
  └──────────┴──────────┴──────────┴──────────┴───────┘


CORE METHODS

claw.hass() Get hass object
claw.state(entityId) Get entity state object
claw.states(filter?) Get filtered states (string/regex/fn)
claw.callService(domain, svc, data) Call HA service
claw.toggle(entityId) Smart toggle (on↔off)
claw.press(entityId) Smart press (button/scene/script)
claw.navigate(path) Navigate to path
claw.moreInfo(entityId) Open more-info dialog
claw.fire(type, detail) Fire custom event
claw.wait(ms) Promise-based delay

DOM UTILITIES

claw.el(tag, attrs, parent) Create element with attributes
claw.remove(idOrEl) Remove element
claw.inject(css) Inject CSS, returns {remove()}
claw.deepQuery(selector) Query across shadow DOM
claw.deepQueryAll(selector) Query all across shadow DOM

WEBSOCKET API (claw.ws)

claw.ws.send(msg) Send message (no response)
claw.ws.call(msg) Send and await response
claw.ws.subscribe(eventType, cb) Subscribe to event type
claw.ws.subscribeMessage(msg, cb) Subscribe with message filter

HTTP API (claw.api)

claw.api.get(path) GET request with auth
claw.api.post(path, data) POST request with auth
claw.api.put(path, data) PUT request with auth
claw.api.delete(path) DELETE request with auth
claw.api.fetch(path, init) Raw fetch with auth

TYPESCRIPT API (claw.ts) [NEW v3.7]

claw.ts.load() Load TS compiler
claw.ts.transpile(code, options) Transpile to JS
claw.ts.run(code, scope) Run TS with scope
claw.ts.card(code, ctx) Run in card context
claw.ts.module(code, scope) Run as ES module

CONFIG ENTRIES (claw.config)

claw.config.entries(params) Get all config entries
claw.config.entry(entryId) Get single entry
claw.config.update(entryId, params) Update entry
claw.config.delete(entryId) Delete entry
claw.config.reload(entryId) Reload entry
claw.config.disable(entryId) Disable entry
claw.config.enable(entryId) Enable entry
claw.config.subscribe(cb) Subscribe to changes

Config Flow:
claw.config.flow.create(handler) Start config flow
claw.config.flow.get(flowId) Get flow state
claw.config.flow.submit(flowId, d) Submit flow step
claw.config.flow.delete(flowId) Abort flow
claw.config.flow.progress() Get flows in progress
claw.config.flow.subscribe(cb) Subscribe to flow events

Options Flow:
claw.config.options.dialog(entryId) Open options dialog
claw.config.options.read(entryId) Read current options
claw.config.options.update(id, d) Update options

REGISTRIES

Areas:
claw.areas.get() Get all areas
claw.areas.create(name, opts) Create area
claw.areas.update(areaId, opts) Update area
claw.areas.delete(areaId) Delete area

Devices:
claw.devices.get(params) Get devices
claw.devices.update(deviceId, opts) Update device

Entities:
claw.entities.get(params) Get entity registry
claw.entities.getEntry(entityId) Get single entity entry
claw.entities.update(entityId, o) Update entity
claw.entities.remove(entityId) Remove entity

AUTOMATIONS (claw.automations)

claw.automations.get() Get all automations
claw.automations.getById(id) Get single automation
claw.automations.create(config) Create automation
claw.automations.update(id, config) Update automation
claw.automations.delete(id) Delete automation
claw.automations.trigger(entityId) Trigger automation

SCRIPTS (claw.scripts)

claw.scripts.get() Get all scripts
claw.scripts.getById(id) Get single script
claw.scripts.create(config) Create script
claw.scripts.update(id, config) Update script
claw.scripts.delete(id) Delete script
claw.scripts.run(entityId, vars) Run script with variables

SCENES (claw.scenes)

claw.scenes.get() Get all scenes
claw.scenes.create(config) Create scene
claw.scenes.update(id, config) Update scene
claw.scenes.delete(id) Delete scene
claw.scenes.activate(entityId) Activate scene

LOVELACE (claw.lovelace)

claw.lovelace.getConfig() Get dashboard config
claw.lovelace.saveConfig(config) Save dashboard config
claw.lovelace.getDashboards() Get all dashboards
claw.lovelace.createDashboard(o) Create dashboard
claw.lovelace.updateDashboard(id,o) Update dashboard
claw.lovelace.deleteDashboard(id) Delete dashboard
claw.lovelace.getResources() Get resources
claw.lovelace.createResource(opts) Create resource
claw.lovelace.updateResource(id,o) Update resource
claw.lovelace.deleteResource(id) Delete resource

SYSTEM (claw.system)

claw.system.info() Get system info
claw.system.restart() Restart Home Assistant
claw.system.stop() Stop Home Assistant
claw.system.checkConfig() Check configuration
claw.system.reloadCore() Reload core config

USERS (claw.users)

claw.users.list() List all users
claw.users.current() Get current user

UI UTILITIES (claw.ui)

claw.ui.main() Get home-assistant-main
claw.ui.sidebar() Get ha-sidebar
claw.ui.drawer() Get ha-drawer
claw.ui.appLayout() Get ha-app-layout
claw.ui.toolbar() Get app-toolbar
claw.ui.panel() Get current panel

SIDEBAR (claw.sidebar)

claw.sidebar.toggle() Toggle sidebar
claw.sidebar.show() Show sidebar
claw.sidebar.hide() Hide sidebar
claw.sidebar.isNarrow() Check if narrow mode

HOOKS (claw.hook)

claw.hook.hass(callback) Hook hass object changes
claw.hook.element(tagName, cb) Hook custom element registration

// Toggle light with TypeScript
<script type="text/typescript">
  const light = claw.state("light.living_room");
  if (light.state === "on") {
    claw.callService("light", "turn_off", { entity_id: "light.living_room" });
  }
</script>

// Subscribe to state changes
<script>
  claw.hook.hass((hass, oldHass) => {
    const temp = hass.states["sensor.temperature"];
    console.log("Temperature:", temp.state);
  });
</script>

// Create automation via API
<script>
  await claw.automations.create({
    alias: "Morning Lights",
    trigger: [{ platform: "time", at: "07:00:00" }],
    action: [{ service: "light.turn_on", target: { entity_id: "light.bedroom" }}]
  });
</script>

// WebSocket subscription
<script>
  claw.ws.subscribe("state_changed", (event) => {
    console.log("Entity changed:", event.data.entity_id);
  });
</script>

// HTTP API call
<script>
  const info = await claw.api.get("config");
  console.log("HA Version:", info.version);
</script>

Full Changelog: v3.6.2...v3.7

Function

Choose a tag to compare

@knoop7 knoop7 released this 26 May 02:35

What's New

UI Refinements

  • Lighter colors for titles and version badges
  • Pure white background for "View Details" button
  • Subtle shadows for collapse panels, search bar, and code editor
  • Removed hover-zoom effect from module cards

Multi-Language Support

  • Card description now supports: English, Simplified Chinese, Traditional Chinese, Japanese, German
  • Configuration editor fully localized with automatic language detection based on Home Assistant settings

Bug Fixes

  • Fixed: border-radius: 50% no longer forced to 10px - circular elements now render correctly
  • Fixed: Missing _loadStoreModules method causing refresh button error
  • Fixed: Update interval input field now displays correctly with native number input

Module Store Improvements

  • Modules now stored as individual YAML files in mods/ folder
  • GitHub Actions automatically syncs modules from Discussions
  • Security validation blocks unsafe external URLs and dangerous code patterns
  • Removed image click-to-zoom (preview only)

Links

Full Changelog: v3.5...v3.6.2

Billionaire

Choose a tag to compare

@knoop7 knoop7 released this 16 May 14:10

Live Hass Proxy

hass injected into <script> is now a live Proxy. Every property access (hass.states, hass.callService, etc.) transparently resolves to the latest HA object at call time. Closures, event handlers, and async callbacks no longer hold stale references.

┌─────────────────┐     set hass()     ┌──────────────┐
│  HA Frontend     │ ──────────────►  │  html-pro-card │
│  (frequent push) │                   │  this._hass    │
└─────────────────┘                   └───────┬────────┘
                                              │
                                    Proxy get(_, prop)
                                              │
                                     ┌────────▼────────┐
                                     │  script scope    │
                                     │  hass.states[id] │  ← always fresh
                                     │  hass.callService│  ← always bound
                                     └─────────────────┘

Implementation: new Proxy({}, { get: (_, prop) => { const v = self._hass[prop]; return typeof v === 'function' ? v.bind(self._hass) : v; }}). Functions are .bind()-ed to preserve this context.

Event-Driven Live Updates

New _watchedEntities + _onHassUpdate mechanism replaces polling for dynamic JS cards.

root._watchedEntities = ['light.', 'climate.living_room'];
root._onHassUpdate = () => renderUI();

Internally, _shouldUpdate() resolves watch patterns into concrete entity ID lists via _resolveWatchList(), caches the result, and performs O(1) reference comparison (oldHass.states[id] !== newHass.states[id]). The resolved list is invalidated when:

  • The watch pattern array reference changes
  • The total entity count in hass changes (new entities added/removed)

Overlay Auto-Delegation

Global overlay container (#html-pro-card-overlay) now has a click event listener using event delegation. Any [data-action] + [data-entity] element appended to the overlay — by any card, at any time — automatically gets toggle/turn_on/turn_off/more-info handling without manual addEventListener calls.

Domain routing in overlay matches card-internal routing:

  • lock → lock/unlock based on current state
  • cover → open_cover/close_cover based on current state
  • button → press
  • scene → turn_on
  • script → script.{name}
  • Others → {domain}.toggle

Overlay Ownership & Isolation

Each card instance generates a unique _instanceId on connectedCallback. The overlay variable passed to scripts is a Proxy that intercepts appendChild/append/prepend and auto-stamps each child with data-hpc-owner="${instanceId}".

On disconnectedCallback, only elements matching the card's own _instanceId are removed — other cards' overlay content is preserved.

Card A overlay content:  <div data-hpc-owner="hpc_a3k2m1">...</div>
Card B overlay content:  <div data-hpc-owner="hpc_x9f4j2">...</div>
                         ↑ Card A disconnect only removes hpc_a3k2m1

Previous behavior (overlay.innerHTML = '') wiped all cards' content on any single card disconnect — this is now fixed.

Overlay Container Fix

Removed overflow: hidden from the global overlay container CSS. Child elements with overflow: auto (e.g., scrollable popup sheets) now scroll correctly.

Removed Global Close Button

The red circle close button (#claw-overlay-close) that auto-appeared at bottom-right is removed. Cards are responsible for their own close UI within overlay content.

Bug Fixes

  • lock domain toggle: lockunlock when locked, lock when unlocked
  • cover domain toggle: close_cover when open/opening, open_cover otherwise
  • Function binding in Proxy: hass.callService() and other methods now have correct this context via .bind(self._hass)
  • root.hass exposed: set hass() now syncs this._rootElement.hass = hass for direct access

README

Complete AI prompt rewrite. Key additions:

  • Live proxy hass documentation
  • _watchedEntities + _onHassUpdate usage pattern
  • Overlay usage rules, auto-delegation, auto-cleanup
  • window.claw API reference table
  • data-map state text mapping
  • border-radius corrected to 10px
  • lock/cover domain mapping
  • Icon rules: mdi, inline SVG, SVG libraries (Lucide/Feather/Tabler)
  • Expanded banned patterns list

Full Changelog: v3.3...v3.5

claw union

Choose a tag to compare

@knoop7 knoop7 released this 12 May 03:34

What's New

Unified Border Radius

  • All ha-card elements now enforce 10px border-radius on creation.
  • Content CSS border-radius values are auto-normalized to 10px at runtime.
  • Eliminates inconsistent card corner styles across dashboards.

Overlay Close Button

  • A persistent close button (bottom-right) appears automatically when overlay content is active.
  • One click clears all overlay effects and temporary elements.
  • Page navigation (location-changed) also clears all overlay content.
  • Browser refresh naturally removes everything — all effects are purely temporary.

window.claw API

  • New global API available inside card <script> blocks.
  • Service calls: claw.callService(), claw.toggle(), claw.press() with smart domain mapping.
  • State access: claw.state(), claw.states() with optional filtering.
  • Navigation: claw.navigate(), claw.moreInfo().
  • Communication: claw.fire(), claw.ws() for raw WebSocket messaging.
  • DOM utilities: claw.el() for element creation, claw.remove(), claw.deepQuery/deepQueryAll for shadow DOM traversal, claw.inject() for CSS injection.
  • Utility: claw.wait(), claw.hass().

Version Tag

  • Added HTML_PRO_CARD_VERSION constant (3.3.0) at file top.
  • Console prints version badge on load for easy identification.
  • Editor header displays current version dynamically.
  • Prevents stale cache issues by making version visible.

Full Changelog: v3.2...v3.3

What's New in v3.2

Choose a tag to compare

@knoop7 knoop7 released this 25 Feb 11:43

1. Integrated Prism Code Editor with full syntax highlighting for HTML, CSS, and JavaScript
2. Added VS Code Dark and Light themes with automatic Home Assistant dark mode detection
3. Built-in search and replace functionality with Ctrl+F and Ctrl+H shortcuts
4. Line numbers display for better code navigation
5. Module store now auto-detects YAML files from the modules directory
6. Removed dependency on modules.json - metadata is parsed directly from YAML files
7. Version badge now links directly to the GitHub repository
8. Automatic border-radius normalization to 20px when pasting content
9. Improved YAML parser with support for scripts array and single-line formats
10. Auto-fill editor fields when pasting complete YAML configurations
11. Fallback textarea for environments where Prism Code Editor cannot load
12. Optimized performance with lazy loading of editor components
13. Updated stub config with cleaner professional design
14. Full i18n support for Chinese and English interfaces
15. Tab key inserts spaces for consistent indentation


Module Store Publishing Guide

To publish a module to the store, create a YAML file in the modules directory with the following format:

id: your-module-id
name: Module Display Name
desc: Brief description of your module
author: your-name
---
type: custom:html-pro-card
content: |
  <your html content here>
update_interval: 10000
do_not_parse: false
ignore_line_breaks: true
scripts:
  - https://cdn.example.com/library.js

Add the filename to modules.txt and submit a pull request.

0.3.0

Choose a tag to compare

@knoop7 knoop7 released this 24 Feb 05:56

YAML Auto-Parse

  • Paste full YAML config directly, auto-parse and fill fields

Scripts Array Support

  • Support both array and single-line scripts format

Module Store Refactor

  • All modules use new YAML format (metadata + --- + config)

UI Improvements

  • New stub config with HTML/CSS/JavaScript tags

v2.9

Choose a tag to compare

@knoop7 knoop7 released this 22 Feb 05:53

HTML Card Pro v2.9 Released
Complete Architecture Refactor | Native HACS Support | JS Engineering

Resolves #4

Core Upgrades
1. Native HACS Integration: One-click install and auto-updates via Home Assistant Community Store. No more manual file copying.
2. Web Components Architecture: Core rewritten with LitElement, Shadow DOM isolation, 300% performance boost.
3. Declarative Data Binding: Bind entities via data-entity attributes. State sync without Jinja2 templates.
4. Dual Mode Compatible: Legacy Jinja2 support retained (do_not_parse: false). Zero-config migration.

Full Changelog (20 Items)

Architecture Refactor
1. Core engine migrated from string templates to Web Components standard
2. Shadow DOM style isolation implemented. CSS pollution eliminated
3. Virtual DOM diff algorithm introduced. Render latency under 10ms
4. Entity state management refactored with centralized data store
5. Hot-reload dev mode supported. Real-time config preview

HACS Support
6. Standard hacs.json config added
7. Automatic version detection and update push implemented
8. Frontend asset loading paths optimized for HACS directory structure
9. Installation validation added. Auto-detects config integrity

JS Enhancements
10. Built-in data-action directive system (toggle/more-info/turn_on)
11. data-brightness and data-temperature two-way slider binding supported
12. data-state-text automatic state text rendering added
13. Global variables hass, config, root exposed for script access
14. External JS library on-demand loading supported (scripts array config)

Performance Optimization
15. Entity state caching mechanism. 80% reduction in unnecessary re-renders
16. Event delegation optimized. 60% lower memory footprint
17. Image lazy loading supported. Faster initial load speed

Stability Fixes
18. Error boundaries handled. Single card failure won't crash entire dashboard
19. Fixed UI freeze when entities become unavailable
20. Mobile touch feedback optimized. Fixed 44px below click area failure