@yacobolo/datastar-prop
v1.0.2
Published
A Datastar plugin that provides property binding to sync element properties with reactive signals, with deep reactivity and Lit component support
Maintainers
Readme
@yacobolo/datastar-prop
A Datastar plugin that provides property binding to sync element properties with reactive signals.
Features
- Property binding - Bind signals directly to DOM element properties (not attributes)
- Deep reactivity - Automatically subscribes to nested signal changes
- Lit component support - Calls
requestUpdate()for proper Lit lifecycle integration - Single & multi-property syntax - Bind one property or multiple at once
- Kebab-case conversion -
data-prop:color-configbecomescolorConfig - Tiny bundle - ~800 bytes minified
Why This Plugin?
Datastar includes a built-in data-attr plugin for setting HTML attributes, but HTML attributes and DOM properties are not the same thing.
While data-attr works great for HTML attributes (like class, id, href), many DOM interactions require setting properties directly:
- Input
valueproperty (vs. thevalueattribute which only sets initial value) - Checkbox
checkedproperty - Element
disabledproperty for real-time form control - Complex objects/arrays to web components (where JSON.stringify won't work)
This plugin fills that gap with added benefits:
- Deep reactivity ensures nested signal changes trigger updates
- Lit support handles Datastar's reactive proxies correctly
Installation
npm install @yacobolo/datastar-propDemo
Usage
This plugin requires an import map to resolve the datastar module:
<script type="importmap">
{
"imports": {
"datastar": "https://cdn.jsdelivr.net/gh/starfederation/[email protected]/bundles/datastar.js"
}
}
</script>
<script type="module">
// Import the plugin - it will auto-register with Datastar
import 'https://cdn.jsdelivr.net/npm/@yacobolo/datastar-prop@1/dist/index.js';
</script>Note: Using @1 will automatically use the latest v1.x.x version.
API
Single Property Binding
Bind a single property using the :property-name suffix:
<input data-prop:value="$mySignal" />
<input data-prop:checked="$isChecked" />
<button data-prop:disabled="$isDisabled">Submit</button>Property names are converted from kebab-case to camelCase:
data-prop:color-config→colorConfigdata-prop:my-property→myProperty
Multiple Property Binding
Bind multiple properties at once using an object:
<input data-prop="{ value: $inputValue, disabled: $isDisabled }" />Complex Objects (Web Components)
Pass complex objects to web components - the main use case for this plugin:
<div data-signals="{
colorConfig: { r: 255, g: 100, b: 50, name: 'Orange' },
items: ['Apple', 'Banana', 'Cherry']
}">
<!-- Pass nested object to Lit component -->
<color-picker data-prop:color-config="$colorConfig"></color-picker>
<!-- Pass array to list component -->
<item-list data-prop:items="$items"></item-list>
</div>The plugin's deep reactivity ensures that changes to nested properties (like $colorConfig.r = 128) will trigger updates.
Deep Reactivity
Unlike simple property binding, this plugin recursively reads all nested properties of your signals. This causes Datastar's effect system to subscribe to changes at any depth:
<div data-signals="{ config: { nested: { deep: 'value' } } }">
<!-- Changes to $config.nested.deep will trigger updates -->
<my-component data-prop:config="$config"></my-component>
</div>Lit Component Support
When working with Lit components, Datastar's reactive proxies maintain the same object reference when internal values change. This would normally prevent Lit from detecting changes.
This plugin automatically calls requestUpdate(propName) on Lit elements, ensuring proper lifecycle updates:
// Your Lit component
@customElement('my-component')
class MyComponent extends LitElement {
@property({ type: Object })
config = {};
updated(changedProperties) {
// This fires correctly when $config changes internally
if (changedProperties.has('config')) {
console.log('Config updated:', this.config);
}
}
}Manual Registration
If you need to register the plugin manually (e.g., for custom bundling):
import propPlugin from '@yacobolo/datastar-prop';
import { attribute, effect } from 'datastar';
// Register manually
attribute(propPlugin(effect));Testing
task testDevelopment
This project uses Task for task automation.
# Show available tasks
task
# Build and run development server
task dev
# Production build
task build
# Run tests
task testReleases
Releases are managed manually using Task commands:
# Bump patch version and publish (1.0.1 → 1.0.2)
task release:patch
# Bump minor version and publish (1.0.1 → 1.1.0)
task release:minor
# Bump major version and publish (1.0.1 → 2.0.0)
task release:majorEach release command will:
- Build the project
- Run tests
- Bump the version
- Publish to npm
- Push tags to GitHub
License
MIT
