Skip to content

Conversation

@ellyxir
Copy link
Contributor

@ellyxir ellyxir commented Oct 14, 2025

Summary by cubic

Adds a “Calendar Basics” tutorial that renders a list of dates with per-day todos using Common Tools state and UI primitives. This teaches how to model lists and maps, and conditionally show content.

  • New Features
    • Added tutorials/code/calendar.tsx with a simple calendar view.
    • Uses Default for dates and cell for a Record-based todo map.
    • Introduces a lifted getTodosForDate helper and conditional “No todos” display.

Tony Espinoza and others added 2 commits October 13, 2025 19:54
Add bidirectional support for HTML5 data-* attributes in JSX templates:

- Write support: setProp() now detects data-* properties and uses
  setAttribute() to properly populate the browser's dataset API
- Read support: serializableEvent() extracts event.target.dataset
  for use in event handlers
- Type safety: Added isHTMLElement() type guard

This enables recipes to pass data through DOM elements and access
it in event handlers via event.target.dataset.

Example usage:
  <div data-date="2025-10-13" onClick={handler}>Click</div>

  handler: (event) => {
    const date = event.target.dataset.date; // Works!
  }

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
…r data, a todo map with date as key and list of string as todo list
ellyxir and others added 8 commits October 14, 2025 18:27
- Handle null/undefined data-* attributes by removing them
- Add proper TypeScript typing for setProp function
- Replace isHTMLElement helper with more robust type checking
- Ensure dataset values are properly stringified in serialization
Add tests covering:
- Setting data-* attributes via setAttribute
- Removing data-* attributes when value is null/undefined
- Converting non-string values to strings
- Updating data-* attributes when values change
- Serializing event.target.dataset

Update MockDoc test utilities:
- Add setAttribute, hasAttribute, removeAttribute methods
- Add dataset property getter with camelCase conversion
- Update custom setProp to handle null/undefined for data-* attributes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 5 files

Prompt for AI agents (all 1 issues)

Understand the root cause of the following 1 issues and fix them.


<file name="packages/html/src/utils.ts">

<violation number="1" location="packages/html/src/utils.ts:138">
The new dataset getter returns a fresh object without wiring assignments back to attribs, so writes like `el.dataset.foo = &quot;bar&quot;` silently fail to create the corresponding `data-foo` attribute. Please make dataset behave like DOMStringMap and sync property writes to attributes.</violation>
</file>

React with 👍 or 👎 to teach cubic. Mention @cubic-dev-ai to give feedback, ask questions, or re-run the review.

}
},
},
dataset: {
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Oct 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new dataset getter returns a fresh object without wiring assignments back to attribs, so writes like el.dataset.foo = "bar" silently fail to create the corresponding data-foo attribute. Please make dataset behave like DOMStringMap and sync property writes to attributes.

Prompt for AI agents
Address the following comment on packages/html/src/utils.ts at line 138:

<comment>The new dataset getter returns a fresh object without wiring assignments back to attribs, so writes like `el.dataset.foo = &quot;bar&quot;` silently fail to create the corresponding `data-foo` attribute. Please make dataset behave like DOMStringMap and sync property writes to attributes.</comment>

<file context>
@@ -94,6 +110,48 @@ export class MockDoc {
+          }
+        },
+      },
+      dataset: {
+        get() {
+          const el = this as any;
</file context>
Fix with Cubic

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 1 file

This change ensures that when writing arrays to cells or pushing to array
cells, all objects are given IDs so they can be stored as separate documents
with links. This applies to both explicitly written arrays and default values
from schemas.

Changes to cell.ts:

1. Modified the `set` method to call `addIDIfNeeded` on each element when
   writing an array, ensuring all objects get IDs before being processed by
   `diffAndUpdate`.

2. Enhanced the `push` method to:
   - Process default values from schemas using `processDefaultValue` to ensure
     they're properly materialized with IDs
   - Apply `addIDIfNeeded` to all elements (both existing defaults and newly
     pushed values) to ensure consistent ID assignment

3. Improved the `update` method's schema validation to:
   - Use `resolveSchema` to properly handle schema references
   - Check for undefined schemas (which allow objects)
   - Consolidate the schema validation logic to determine if objects are
     allowed

4. Added new `addIDIfNeeded` helper function that:
   - Checks if a value is an object without an ID
   - Generates a new ID from the frame's counter if needed
   - Preserves existing IDs when present

New tests in cell.test.ts:

- "set operations with arrays" suite:
  - Tests that objects written as arrays each get their own document ID
  - Verifies that existing IDs are preserved during array writes
  - Uses `asSchema` with `asCell: true` to read back as cells and verify
    each element has a distinct document ID

- "push operations with default values" suite:
  - Tests that default values from schemas are properly materialized with IDs
  - Verifies all objects (defaults + pushed) get unique IDs
  - Tests push operations both with and without schema defaults

These changes ensure that array operations consistently create separate
documents for each object, maintaining proper referential structure in the
storage layer.
seefeldb and others added 6 commits October 15, 2025 18:07
…eate-cells-on-array-writes' into ellyse/tutorials-calendar-basics
Move data URI inlining logic to occur before write redirect (alias)
handling in normalizeAndDiff. This ensures the correct evaluation order
when a data URI contains a redirect link.

Previously, when newValue was a data URI containing a redirect, the
code would:
1. Check currentValue for redirects (line 290)
2. Follow currentValue redirect if present
3. Process data URI inlining later (line 318)

This caused the redirect within the data URI to be written to the wrong
location - it would follow the currentValue redirect first, then inline
the data URI, resulting in the redirect being written to the destination
of the currentValue alias instead of to the intended target.

The fix reorders the logic so data URIs are inlined immediately after
unwrapping proxies and cells (line 212), before any redirect handling.
This preserves the invariant that redirect handling at line 290 only
applies when newValue is not itself an alias.

The order is now:
1. Unwrap proxies/cells
2. Inline data URIs (exposing any contained redirects)
3. Handle redirects in newValue
4. Handle redirects in currentValue

This ensures redirects contained in data URIs are properly recognized
and handled as part of newValue, not incorrectly written through a
currentValue redirect.
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 7 files

Prompt for AI agents (all 1 issues)

Understand the root cause of the following 1 issues and fix them.


<file name="packages/runner/src/cell.ts">

<violation number="1" location="packages/runner/src/cell.ts:456">
Calling `recursivelyAddIDIfNeeded` here converts `Cell` arguments into plain objects before `diffAndUpdate` runs, so flows like `cell.set(otherCell)` or `push(cell)` stop emitting links and instead serialize the cell’s internal fields, breaking link-based updates.</violation>
</file>

React with 👍 or 👎 to teach cubic. Mention @cubic-dev-ai to give feedback, ask questions, or re-run the review.

if (!this.synced) this.sync();

// Looks for arrays and makes sure each object gets its own doc.
newValue = recursivelyAddIDIfNeeded(newValue);
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Oct 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calling recursivelyAddIDIfNeeded here converts Cell arguments into plain objects before diffAndUpdate runs, so flows like cell.set(otherCell) or push(cell) stop emitting links and instead serialize the cell’s internal fields, breaking link-based updates.

Prompt for AI agents
Address the following comment on packages/runner/src/cell.ts at line 456:

<comment>Calling `recursivelyAddIDIfNeeded` here converts `Cell` arguments into plain objects before `diffAndUpdate` runs, so flows like `cell.set(otherCell)` or `push(cell)` stop emitting links and instead serialize the cell’s internal fields, breaking link-based updates.</comment>

<file context>
@@ -448,6 +452,9 @@ export class RegularCell&lt;T&gt; implements Cell&lt;T&gt; {
     if (!this.synced) this.sync();
 
+    // Looks for arrays and makes sure each object gets its own doc.
+    newValue = recursivelyAddIDIfNeeded(newValue);
+
     // TODO(@ubik2) investigate whether i need to check classified as i walk down my own obj
</file context>
Fix with Cubic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants