component_reference — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited component_reference (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
STOP. THIS IS THE AUTHORITATIVE REFERENCE FOR ALL COMPONENTS. YOU MUST USE THE EXACT EVENT SIGNATURES DOCUMENTED HERE. THERE ARE NO EXCEPTIONS. NO WORKAROUNDS. NO DEVIATIONS.
These are the ONLY events that work for updating widgets. Use send_event tool with these event types:
| Event Type | Payload | Description |
|---|---|---|
grid:update-data | {"data": [...rows...], "strategy": "set"} | Replace all rows |
grid:update-data | {"data": [...rows...], "strategy": "append"} | Append rows |
grid:update-data | {"data": [...rows...], "strategy": "update"} | Update existing rows |
grid:update-columns | {"columnDefs": [...]} | Update column definitions |
grid:update-cell | {"rowId": "row-1", "colId": "price", "value": 99.50} | Update single cell |
| Event Type | Payload | Description |
|---|---|---|
grid:request-state | {} | Request current grid state |
grid:request-state | {"gridId": "my-grid"} | Request specific grid's state |
grid:restore-state | {"state": {...savedState...}} | Restore saved grid state |
grid:reset-state | {"hard": false} | Soft reset (keeps column order) |
grid:reset-state | {"hard": true} | Hard reset (full reset) |
Response Event: grid:state-response with {"gridId": "...", "state": {...}}
State Object Contents:
| Event Type | Payload | Description |
|---|---|---|
plotly:update-figure | {"data": [...], "layout": {...}} | Full figure update |
plotly:update-layout | {"layout": {...}} | Layout only update |
plotly:reset-zoom | {} | Reset chart zoom to original |
| Event Type | Payload | Description |
|---|---|---|
plotly:request-state | {} | Request current chart state |
plotly:request-state | {"chartId": "my-chart"} | Request specific chart's state |
Response Event: plotly:state-response with {"chartId": "...", "data": [...], "layout": {...}}
| Event Type | Payload | Description |
|---|---|---|
plotly:export-data | {} | Export chart data |
plotly:export-data | {"chartId": "my-chart"} | Export specific chart's data |
Response Event: plotly:export-response with {"data": [{"traceIndex": 0, "name": "...", "x": [...], "y": [...], "type": "..."}]}
| Event Type | Payload | Description |
|---|---|---|
pywry:set-content | {"id": "elementId", "text": "..."} | Set text content |
pywry:set-content | {"id": "elementId", "html": "..."} | Set HTML content |
pywry:set-style | {"id": "elementId", "styles": {"color": "red"}} | Update CSS styles |
| Event Type | Payload | Description |
|---|---|---|
pywry:update-theme | {"theme": "dark"} | Switch theme (dark/light/system) |
pywry:update-theme | {"theme": "ag-theme-alpine-dark"} | AG Grid theme |
pywry:update-theme | {"theme": "plotly_dark"} | Plotly template |
Use show_toast tool instead, or:
| Event Type | Payload | Description |
|---|---|---|
pywry:alert | {"message": "...", "type": "info"} | info, success, warning, error |
| Event Type | Payload | Description |
|---|---|---|
toolbar:set-value | {"componentId": "my-select", "value": "option2"} | Set single component value |
toolbar:set-values | {"values": {"select-1": "A", "toggle-1": true}} | Set multiple values at once |
toolbar:request-state | {"componentId": "my-input"} | Request single component value |
toolbar:request-state | {"toolbarId": "top-toolbar"} | Request all values in toolbar |
toolbar:request-state | {} | Request all toolbar values |
Response Event: toolbar:state-response with {"componentId": "...", "value": ...} or {"values": {...}}
Supported Components for set-value:
select: {"componentId": "id", "value": "option-value"}multiselect: {"componentId": "id", "value": ["a", "b"]}toggle: {"componentId": "id", "value": true}checkbox: {"componentId": "id", "value": true}text/textarea/search: {"componentId": "id", "value": "text"}number: {"componentId": "id", "value": 42}slider: {"componentId": "id", "value": 50}range: {"componentId": "id", "value": {"start": 10, "end": 90}}tabs/radio: {"componentId": "id", "value": "tab-value"}Note: secret inputs cannot be set via toolbar:set-value for security.
A clickable button that emits an event.
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type | "button" | ✅ YES | - | Component type identifier |
label | string | ✅ YES | - | Button text |
event | string | ✅ YES | - | Event name (format: namespace:action) |
variant | string | ❌ | "primary" | Style: primary, secondary, neutral, ghost, outline, danger, warning, icon |
size | string | ❌ | null | Size: xs, sm, lg, xl |
data | object | ❌ | {} | Extra data payload sent with event |
disabled | boolean | ❌ | false | Disable the button |
description | string | ❌ | "" | Tooltip on hover |
{
componentId: "button-abc123", // Auto-generated component ID
...data // Your custom data object spread in
}When event follows elementId:action pattern, these actions work automatically:
| Event Pattern | Behavior |
|---|---|
myId:increment | Finds id="myId", parses as number, adds 1 |
myId:decrement | Finds id="myId", parses as number, subtracts 1 |
myId:reset | Finds id="myId", sets to 0 |
myId:toggle | Finds id="myId", toggles true/false |
{
"type": "button",
"label": "Submit",
"event": "form:submit",
"variant": "primary",
"data": {"formId": "contact"}
}A single-select dropdown.
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type | "select" | ✅ YES | - | Component type identifier |
event | string | ✅ YES | - | Event name (format: namespace:action) |
options | array | ✅ YES | - | Array of {label, value} objects |
selected | string | ❌ | "" | Initially selected value |
label | string | ❌ | "" | Label text |
searchable | boolean | ❌ | false | Enable search filtering |
disabled | boolean | ❌ | false | Disable the dropdown |
{
value: "selected_value", // The selected option's value
componentId: "select-abc123"
}{
"type": "select",
"label": "Theme:",
"event": "theme:change",
"options": [
{"label": "Dark", "value": "dark"},
{"label": "Light", "value": "light"},
{"label": "System", "value": "system"}
],
"selected": "dark"
}A multi-select dropdown with checkboxes.
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type | "multiselect" | ✅ YES | - | Component type identifier |
event | string | ✅ YES | - | Event name |
options | array | ✅ YES | - | Array of {label, value} objects |
selected | array | ❌ | [] | Initially selected values |
label | string | ❌ | "" | Label text |
disabled | boolean | ❌ | false | Disable the dropdown |
{
values: ["value1", "value2"], // Array of selected values
componentId: "multiselect-abc123"
}{
"type": "multiselect",
"label": "Columns:",
"event": "columns:filter",
"options": [
{"label": "Name", "value": "name"},
{"label": "Age", "value": "age"},
{"label": "City", "value": "city"}
],
"selected": ["name", "age"]
}A toggle switch for boolean values.
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type | "toggle" | ✅ YES | - | Component type identifier |
event | string | ✅ YES | - | Event name |
value | boolean | ❌ | false | Initial state |
label | string | ❌ | "" | Label text |
disabled | boolean | ❌ | false | Disable the toggle |
{
value: true, // Boolean: true or false
componentId: "toggle-abc123"
}{
"type": "toggle",
"label": "Dark Mode:",
"event": "theme:toggle",
"value": true
}A single checkbox for boolean values.
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type | "checkbox" | ✅ YES | - | Component type identifier |
event | string | ✅ YES | - | Event name |
value | boolean | ❌ | false | Initial checked state |
label | string | ✅ YES | - | Label text (displayed next to checkbox) |
disabled | boolean | ❌ | false | Disable the checkbox |
{
value: true, // Boolean: true or false
componentId: "checkbox-abc123"
}{
"type": "checkbox",
"label": "Enable notifications",
"event": "settings:notify",
"value": true
}A group of radio buttons for single selection.
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type | "radio" | ✅ YES | - | Component type identifier |
event | string | ✅ YES | - | Event name |
options | array | ✅ YES | - | Array of {label, value} objects |
selected | string | ❌ | "" | Initially selected value |
label | string | ❌ | "" | Group label |
direction | string | ❌ | "horizontal" | Layout: horizontal or vertical |
disabled | boolean | ❌ | false | Disable all radios |
{
value: "selected_value", // The selected option's value
componentId: "radio-abc123"
}{
"type": "radio",
"label": "View:",
"event": "view:change",
"options": [
{"label": "List", "value": "list"},
{"label": "Grid", "value": "grid"},
{"label": "Card", "value": "card"}
],
"selected": "list",
"direction": "horizontal"
}Tab-style buttons for single selection (visually different from RadioGroup).
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type | "tabs" | ✅ YES | - | Component type identifier |
event | string | ✅ YES | - | Event name |
options | array | ✅ YES | - | Array of {label, value} objects |
selected | string | ❌ | "" | Initially selected value |
label | string | ❌ | "" | Group label |
size | string | ❌ | "md" | Size: sm, md, lg |
disabled | boolean | ❌ | false | Disable all tabs |
{
value: "selected_value", // The selected tab's value
componentId: "tab-abc123"
}{
"type": "tabs",
"label": "Mode:",
"event": "mode:switch",
"options": [
{"label": "Edit", "value": "edit"},
{"label": "Preview", "value": "preview"},
{"label": "Split", "value": "split"}
],
"selected": "edit"
}A single-line text input with debounced events.
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type | "text" | ✅ YES | - | Component type identifier |
event | string | ✅ YES | - | Event name |
value | string | ❌ | "" | Initial value |
placeholder | string | ❌ | "" | Placeholder text |
label | string | ❌ | "" | Label text |
debounce | integer | ❌ | 300 | Debounce milliseconds |
disabled | boolean | ❌ | false | Disable the input |
{
value: "user typed text", // The current input value
componentId: "text-abc123"
}{
"type": "text",
"label": "Name:",
"event": "form:name",
"placeholder": "Enter your name",
"debounce": 300
}A multi-line text area with resizing.
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type | "textarea" | ✅ YES | - | Component type identifier |
event | string | ✅ YES | - | Event name |
value | string | ❌ | "" | Initial value |
placeholder | string | ❌ | "" | Placeholder text |
label | string | ❌ | "" | Label text |
rows | integer | ❌ | 3 | Number of visible rows |
cols | integer | ❌ | 40 | Number of visible columns |
resize | string | ❌ | "both" | Resize: both, horizontal, vertical, none |
debounce | integer | ❌ | 300 | Debounce milliseconds |
disabled | boolean | ❌ | false | Disable the textarea |
{
value: "multi-line\ntext content", // The textarea content
componentId: "textarea-abc123"
}{
"type": "textarea",
"label": "Notes:",
"event": "form:notes",
"placeholder": "Enter your notes...",
"rows": 5,
"resize": "vertical"
}A search input with magnifying glass icon.
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type | "search" | ✅ YES | - | Component type identifier |
event | string | ✅ YES | - | Event name |
value | string | ❌ | "" | Initial value |
placeholder | string | ❌ | "Search..." | Placeholder text |
label | string | ❌ | "" | Label text |
debounce | integer | ❌ | 300 | Debounce milliseconds |
disabled | boolean | ❌ | false | Disable the input |
{
value: "search query", // The search text
componentId: "search-abc123"
}{
"type": "search",
"label": "Filter:",
"event": "table:filter",
"placeholder": "Type to filter...",
"debounce": 200
}A numeric input with optional constraints.
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type | "number" | ✅ YES | - | Component type identifier |
event | string | ✅ YES | - | Event name |
value | number | ❌ | null | Initial value |
min | number | ❌ | null | Minimum value |
max | number | ❌ | null | Maximum value |
step | number | ❌ | null | Step increment |
label | string | ❌ | "" | Label text |
disabled | boolean | ❌ | false | Disable the input |
{
value: 42, // The numeric value
componentId: "number-abc123"
}{
"type": "number",
"label": "Quantity:",
"event": "cart:quantity",
"value": 1,
"min": 1,
"max": 100,
"step": 1
}A date picker input.
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type | "date" | ✅ YES | - | Component type identifier |
event | string | ✅ YES | - | Event name |
value | string | ❌ | "" | Initial date (YYYY-MM-DD) |
min | string | ❌ | "" | Minimum date (YYYY-MM-DD) |
max | string | ❌ | "" | Maximum date (YYYY-MM-DD) |
label | string | ❌ | "" | Label text |
disabled | boolean | ❌ | false | Disable the input |
{
value: "2025-01-29", // Date string in YYYY-MM-DD format
componentId: "date-abc123"
}{
"type": "date",
"label": "Start Date:",
"event": "filter:startDate",
"value": "2025-01-01",
"min": "2020-01-01",
"max": "2030-12-31"
}A single-value slider.
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type | "slider" | ✅ YES | - | Component type identifier |
event | string | ✅ YES | - | Event name |
value | number | ❌ | 50 | Initial value |
min | number | ❌ | 0 | Minimum value |
max | number | ❌ | 100 | Maximum value |
step | number | ❌ | 1 | Step increment |
show_value | boolean | ❌ | true | Show value display |
debounce | integer | ❌ | 50 | Debounce milliseconds |
label | string | ❌ | "" | Label text |
disabled | boolean | ❌ | false | Disable the slider |
{
value: 75, // The slider value
componentId: "slider-abc123"
}{
"type": "slider",
"label": "Volume:",
"event": "audio:volume",
"value": 50,
"min": 0,
"max": 100,
"step": 5,
"show_value": true
}A dual-handle range slider for min/max selection.
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type | "range" | ✅ YES | - | Component type identifier |
event | string | ✅ YES | - | Event name |
start | number | ❌ | 0 | Initial start value |
end | number | ❌ | 100 | Initial end value |
min | number | ❌ | 0 | Minimum value |
max | number | ❌ | 100 | Maximum value |
step | number | ❌ | 1 | Step increment |
show_value | boolean | ❌ | true | Show value displays |
debounce | integer | ❌ | 50 | Debounce milliseconds |
label | string | ❌ | "" | Label text |
disabled | boolean | ❌ | false | Disable the slider |
{
start: 25, // Start/min value
end: 75, // End/max value
componentId: "range-abc123"
}{
"type": "range",
"label": "Price Range:",
"event": "filter:price",
"start": 100,
"end": 500,
"min": 0,
"max": 1000,
"step": 10,
"show_value": true
}A password/secret input with visibility toggle and copy button.
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type | "secret" | ✅ YES | - | Component type identifier |
event | string | ✅ YES | - | Event name |
value | string | ❌ | "" | Initial secret value (stored securely) |
placeholder | string | ❌ | "" | Placeholder text |
label | string | ❌ | "" | Label text |
show_toggle | boolean | ❌ | true | Show visibility toggle button |
show_copy | boolean | ❌ | true | Show copy button |
debounce | integer | ❌ | 300 | Debounce milliseconds |
disabled | boolean | ❌ | false | Disable the input |
On value change:
{
value: "base64_encoded_value", // Base64 encoded secret
encoded: true,
componentId: "secret-abc123"
}On reveal request: (event: {event}:reveal)
{
componentId: "secret-abc123"
}On copy request: (event: {event}:copy)
{
componentId: "secret-abc123"
}{
"type": "secret",
"label": "API Key:",
"event": "settings:apiKey",
"placeholder": "Enter your API key",
"show_toggle": true,
"show_copy": true
}A container for custom HTML content.
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type | "div" | ✅ YES | - | Component type identifier |
content | string | ✅ YES | - | HTML content |
component_id | string | ❌ | auto | ID for updates via set_content |
class_name | string | ❌ | "" | CSS class name |
style | string | ❌ | "" | Inline CSS styles |
children | array | ❌ | null | Nested toolbar items |
No automatic events. Use for layout/display only, or add interactive children.
{
"type": "div",
"content": "<span style=\"color: green\">Online</span>",
"component_id": "status-display",
"style": "padding: 8px; font-weight: bold"
}A scrolling text ticker component.
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
type | "marquee" | ✅ YES | - | Component type identifier |
text | string | ✅ YES | - | Scrolling text content |
event | string | ❌ | - | Event name (if clickable) |
speed | number | ❌ | 15 | Seconds per scroll cycle (1-300) |
direction | string | ❌ | "left" | Direction: left, right, up, down |
behavior | string | ❌ | "scroll" | Behavior: scroll, alternate, slide, static |
pause_on_hover | boolean | ❌ | true | Pause on mouse hover |
gap | integer | ❌ | 50 | Gap between content (pixels) |
clickable | boolean | ❌ | false | Emit event on click |
separator | string | ❌ | "" | Separator between repeats |
component_id | string | ❌ | auto | ID for updates |
{
value: "the marquee text", // The text content
componentId: "marquee-abc123"
}Use set_content or update_marquee tools to update:
// Update text
{id: "marquee-abc123", text: "New content!"}
// Update speed
{id: "marquee-abc123", speed: 10}
// Pause/resume
{id: "marquee-abc123", paused: true}{
"type": "marquee",
"text": "Breaking News: Market is up 5% • Weather: Sunny • More updates...",
"speed": 20,
"direction": "left",
"pause_on_hover": true,
"clickable": true,
"event": "news:click"
}A helper for creating updatable items within a Marquee.
Note: TickerItem is used with build_ticker_item tool, not as a direct toolbar item.
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
ticker | string | ✅ YES | - | Unique identifier (e.g., "AAPL") |
text | string | ❌ | "" | Text content |
html | string | ❌ | "" | HTML content (overrides text) |
class_name | string | ❌ | "" | CSS classes |
style | string | ❌ | "" | Inline styles |
update_ticker_item{
ticker: "AAPL",
text: "AAPL $186.25 ▲",
styles: {color: "#22c55e"},
class_add: "stock-up",
class_remove: "stock-down"
}# Build ticker items
items = [
build_ticker_item(ticker="AAPL", text="AAPL $185.50"),
build_ticker_item(ticker="GOOGL", text="GOOGL $142.20"),
]
# Use in marquee
marquee_text = " • ".join(items)All components go inside the toolbars array. Each toolbar has:
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
position | string | ✅ YES | - | Position: top, bottom, left, right, header, footer, inside |
items | array | ✅ YES | - | Array of components |
class_name | string | ❌ | "" | CSS class for toolbar |
{
"html": "<div id=\"content\">Main content here</div>",
"title": "My Widget",
"height": 600,
"toolbars": [
{
"position": "top",
"items": [
{"type": "button", "label": "Save", "event": "file:save", "variant": "primary"},
{"type": "button", "label": "Cancel", "event": "file:cancel", "variant": "secondary"},
{"type": "select", "event": "file:format", "options": [
{"label": "JSON", "value": "json"},
{"label": "CSV", "value": "csv"}
], "selected": "json"}
]
},
{
"position": "bottom",
"items": [
{"type": "div", "content": "Status: Ready", "component_id": "status"},
{"type": "slider", "event": "zoom:level", "value": 100, "min": 50, "max": 200, "label": "Zoom:"}
]
}
]
}namespace:actionAll events MUST follow this pattern:
form, view, settings)submit, change, api-key)✅ form:submit ✅ view:change ✅ settings:api-key ✅ counter:increment ✅ filter:price-range
❌ submit (no namespace) ❌ form-submit (hyphen instead of colon) ❌ 123:action (namespace starts with number) ❌ :action (empty namespace) ❌ form: (empty action)
pywry - Internal PyWry eventsplotly - Plotly chart events (except plotly:modebar-*)grid - AG Grid events| Type Value | Component | Primary Event Payload |
|---|---|---|
button | Button | {componentId, ...data} |
select | Select | {value, componentId} |
multiselect | MultiSelect | {values: [], componentId} |
toggle | Toggle | {value: boolean, componentId} |
checkbox | Checkbox | {value: boolean, componentId} |
radio | RadioGroup | {value, componentId} |
tabs | TabGroup | {value, componentId} |
text | TextInput | {value, componentId} |
textarea | TextArea | {value, componentId} |
search | SearchInput | {value, componentId} |
number | NumberInput | {value: number, componentId} |
date | DateInput | {value: "YYYY-MM-DD", componentId} |
slider | SliderInput | {value: number, componentId} |
range | RangeInput | {start, end, componentId} |
secret | SecretInput | {value: base64, encoded: true, componentId} |
div | Div | No events (display only) |
marquee | Marquee | {value, componentId} (if clickable) |
END OF REFERENCE. USE THESE EXACT STRUCTURES. NO EXCEPTIONS.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.