caspian-utils 0.1.16 → 0.1.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -418,10 +418,10 @@ Global helpers exposed through the `pp` singleton and also merged into the compo
418
418
  Notes:
419
419
 
420
420
  - The global `pp` singleton auto-mounts once the runtime is loaded and the DOM is ready. Manual `pp.mount()` is still safe because it short-circuits after the first mount.
421
- - `pp.state` setters accept either a value or an updater function.
422
- - `pp.effect` and `pp.layoutEffect` are cleanup-style hooks. They may return only a synchronous cleanup function; returning a promise warns and is ignored, so start async work inside the effect instead.
423
- - A function used through `pp-ref` may return a synchronous cleanup function. PulsePoint runs it when that callback ref is replaced or detached; callbacks that do not return cleanup retain the legacy `callback(null)` detach behavior.
424
- - `pp.portal(ref)` defaults to `document.body` when no target is provided.
421
+ - `pp.state` setters accept either a value or an updater function.
422
+ - `pp.effect` and `pp.layoutEffect` are cleanup-style hooks. They may return only a synchronous cleanup function; returning a promise warns and is ignored, so start async work inside the effect instead.
423
+ - A function used through `pp-ref` may return a synchronous cleanup function. PulsePoint runs it when that callback ref is replaced or detached; callbacks that do not return cleanup retain the legacy `callback(null)` detach behavior.
424
+ - `pp.portal(ref)` defaults to `document.body` when no target is provided.
425
425
  - Older docs may call the RPC helper `pp.fetchFunction()`. In the current bundled runtime the implemented global API is `pp.rpc()`.
426
426
  - Keep template-facing bindings at the top level so the AST-based exporter can see them.
427
427
  - For predictable code generation, prefer passing an explicit dependency array to `pp.effect`, `pp.layoutEffect`, `pp.memo`, and `pp.callback`.
@@ -586,22 +586,23 @@ Nested components:
586
586
  - Nested roots that contain their own `script` block are masked during parent template compilation.
587
587
  - Scriptless nested component roots are not fully masked during parent template compilation in the current source. Avoid generating child-local interpolations inside a nested root unless that child has its own `script` block.
588
588
 
589
- ## Template expressions and attributes
590
-
591
- - Use `{expression}` in text nodes and attribute values.
592
- - Follow HTML-first attribute naming. Native event attributes are lowercase DOM event attributes (`onclick`, `oninput`, `onsubmit`). Every other attribute on a component boundary is a prop: kebab-case names become camel-cased only inside `pp.props` (`selected-value` becomes `selectedValue`, `open-change` becomes `openChange`, and `on-open-change` becomes `onOpenChange`). A function prop does not need an `on-` prefix; that prefix is only an API naming convention. Use `on-click` when a component intentionally exposes an `onClick` prop, because lowercase `onclick` is reserved for the native DOM event on the boundary element.
593
- - Pure bindings like `value="{count}"` are evaluated as expressions.
589
+ ## Template expressions and attributes
590
+
591
+ - Use `{expression}` in text nodes and attribute values.
592
+ - Follow HTML-first attribute naming. Native event attributes are lowercase DOM event attributes (`onclick`, `oninput`, `onsubmit`). Every other attribute on a component boundary is a prop: kebab-case names become camel-cased only inside `pp.props` (`selected-value` becomes `selectedValue`, `open-change` becomes `openChange`, and `on-open-change` becomes `onOpenChange`). A function prop does not need an `on-` prefix; that prefix is only an API naming convention. Use `on-click` when a component intentionally exposes an `onClick` prop, because lowercase `onclick` is reserved for the native DOM event on the boundary element.
593
+ - Pure bindings like `value="{count}"` are evaluated as expressions.
594
594
  - For dynamic inline styles in authored templates, prefer `pp-style="{styleText}"` over `style="{styleText}"` so HTML/CSS tooling does not parse the brace expression as raw CSS.
595
595
  - `pp-style` is an authoring alias. The compiler rewrites it to a native `style` attribute in rendered output.
596
596
  - If the same element already has a static `style` attribute, `pp-style` is merged into that `style` value during compilation.
597
597
  - Mixed text like `class="card {isActive ? 'active' : ''}"` is supported.
598
- - Arrays in template expressions are joined without commas.
599
- - `null`, `undefined`, and boolean expression results render as an empty string in text output.
600
- - Plain objects, functions, and symbols are invalid template children; the runtime warns and omits them instead of rendering accidental strings such as `[object Object]`.
598
+ - Arrays in template expressions are joined without commas.
599
+ - `null`, `undefined`, and boolean expression results render as an empty string in text output.
600
+ - Plain objects, functions, and symbols are invalid template children; the runtime warns and omits them instead of rendering accidental strings such as `[object Object]`.
601
601
  - Supported boolean attributes are normalized so truthy values emit the bare attribute and falsy values remove it.
602
+ - Boolean expressions bound to string-valued attributes such as `aria-pressed`, `aria-expanded`, and `data-*` serialize as the literal strings `"true"` and `"false"`, including on nested component boundaries.
602
603
  - `<textarea value="{draft}"></textarea>` is normalized into textarea content.
603
604
  - Use `pp-spread="{...attrs}"` to spread an object expression into attributes.
604
- - `pp-spread` omits nullish values, omits known HTML boolean attributes when their value is `false`, emits them bare when `true`, preserves string-valued `aria-*`/`data-*` booleans, and escapes `&`, `"`, and `<` in emitted attribute values.
605
+ - `pp-spread` omits nullish values, omits known HTML boolean attributes when their value is `false`, emits them bare when `true`, preserves string-valued `aria-*`/`data-*` booleans, and escapes `&`, `"`, and `<` in emitted attribute values.
605
606
  - Use plain `key` for keyed diffing. `pp-key` is not implemented.
606
607
 
607
608
  Example:
@@ -632,23 +633,23 @@ The render pipeline wraps each top-level `pp-component` root in an inert `<templ
632
633
  - Do not add per-tag workarounds to dodge first-paint validation (static-path `hidden` toggles instead of binding `d`, `data-*` URL holders, `hidden`-gated `<img src>`, or an SSR-resolved initial value). The deferral removes the whole class at once.
633
634
  - `pp-style` and the `<input>`/`<select>`/`checked`/`defaultvalue`/`<textarea>` value rewrites still apply — but for different reasons that deferral does not replace: authoring-source tooling (`style="{...}"` breaks HTML/CSS linters) and attribute-vs-property correctness for controlled form fields.
634
635
 
635
- ## Refs
636
-
637
- - Refs are for imperative element access. Do not use `pp-ref` as the default way to read normal form input values on submit; prefer the form's `onsubmit` event plus `Object.fromEntries(new FormData(event.currentTarget).entries())`.
638
- - `pp-ref` works on native elements and on `x-*` component tags. On a component tag it resolves in the parent's scope and binds to the component's concrete root DOM element, so `<x-input pp-ref="{nameInput}" />` exposes the rendered `<input>` without a wrapper or `querySelector(...)`.
639
- - Use the bare-name form, such as `pp-ref="nameInput"`, when the ref object or callback is already available under that name in scope. The runtime resolves this form by scope lookup.
640
- - Use the brace-expression form, such as `pp-ref="{nameInput}"`, `pp-ref="{registerRef(id)}"`, or `pp-ref="{el => setNode(el)}"`, when the compiler should capture an expression. This is the preferred general form for component tags and dynamic or callback expressions.
641
- - `pp.ref(null)` is the normal way to create a ref object.
642
- - Callback refs and `{ current }` refs are both supported.
643
- - Captured brace-form refs are compiled into an internal `data-pp-ref` token and rebound after render.
644
- - Component refs are attached before layout effects and passive effects run, and detach with `null` (or a callback's returned synchronous cleanup) when the owning element unmounts.
645
- - A composition component whose root is another `x-*` component forwards the ref through Caspian's layout-neutral component hosts to the eventual concrete DOM root.
646
- - Plain `pp-ref` bindings are preserved across rerenders, including no-op rerenders that skip DOM diffing.
636
+ ## Refs
637
+
638
+ - Refs are for imperative element access. Do not use `pp-ref` as the default way to read normal form input values on submit; prefer the form's `onsubmit` event plus `Object.fromEntries(new FormData(event.currentTarget).entries())`.
639
+ - `pp-ref` works on native elements and on `x-*` component tags. On a component tag it resolves in the parent's scope and binds to the component's concrete root DOM element, so `<x-input pp-ref="{nameInput}" />` exposes the rendered `<input>` without a wrapper or `querySelector(...)`.
640
+ - Use the bare-name form, such as `pp-ref="nameInput"`, when the ref object or callback is already available under that name in scope. The runtime resolves this form by scope lookup.
641
+ - Use the brace-expression form, such as `pp-ref="{nameInput}"`, `pp-ref="{registerRef(id)}"`, or `pp-ref="{el => setNode(el)}"`, when the compiler should capture an expression. This is the preferred general form for component tags and dynamic or callback expressions.
642
+ - `pp.ref(null)` is the normal way to create a ref object.
643
+ - Callback refs and `{ current }` refs are both supported.
644
+ - Captured brace-form refs are compiled into an internal `data-pp-ref` token and rebound after render.
645
+ - Component refs are attached before layout effects and passive effects run, and detach with `null` (or a callback's returned synchronous cleanup) when the owning element unmounts.
646
+ - A composition component whose root is another `x-*` component forwards the ref through Caspian's layout-neutral component hosts to the eventual concrete DOM root.
647
+ - Plain `pp-ref` bindings are preserved across rerenders, including no-op rerenders that skip DOM diffing.
647
648
  - Ref callbacks may be called with `null` during cleanup.
648
649
  - The runtime generates `data-pp-ref` internally. Do not author it.
649
650
  - Do not author `pp-event-owner`, `pp-owner`, or `pp-dynamic-*` attributes by hand.
650
651
 
651
- Example:
652
+ Example:
652
653
 
653
654
  ```html
654
655
  <div>
@@ -658,29 +659,29 @@ Example:
658
659
  <script>
659
660
  const nameInput = pp.ref(null);
660
661
  </script>
661
- </div>
662
- ```
663
-
664
- Component example:
665
-
666
- ```html
667
- <div>
668
- <x-input pp-ref="{nameInput}" name="name" />
669
- <button onclick="nameInput.current?.focus()">Focus</button>
670
-
671
- <script>
672
- const nameInput = pp.ref(null);
673
- </script>
674
- </div>
675
- ```
662
+ </div>
663
+ ```
664
+
665
+ Component example:
666
+
667
+ ```html
668
+ <div>
669
+ <x-input pp-ref="{nameInput}" name="name" />
670
+ <button onclick="nameInput.current?.focus()">Focus</button>
671
+
672
+ <script>
673
+ const nameInput = pp.ref(null);
674
+ </script>
675
+ </div>
676
+ ```
676
677
 
677
678
  ## Lists and keyed diffing
678
679
 
679
680
  - Use `pp-for` only on `<template>`.
680
681
  - Supported forms are `item in items` and `(item, index) in items`.
681
- - Collections may be arrays or synchronous iterables such as `Set`, `Map`, typed arrays, strings, and generators. Non-null non-iterable values warn and render as empty lists.
682
+ - Collections may be arrays or synchronous iterables such as `Set`, `Map`, typed arrays, strings, and generators. Non-null non-iterable values warn and render as empty lists.
682
683
  - Loop content can contain interpolations, events, refs, and nested components.
683
- - Event handlers inside loops capture each rendered item, so later collection changes do not retarget an existing row handler.
684
+ - Event handlers inside loops capture each rendered item, so later collection changes do not retarget an existing row handler.
684
685
  - Use stable unique `key` values on repeated sibling elements.
685
686
  - Duplicate keys trigger warnings and reduce diff quality.
686
687
  - Keyed reconciliation preserves DOM identity across reorders and insertions.
@@ -737,9 +738,9 @@ Example:
737
738
  - Push navigation resets window scroll to the top.
738
739
  - Saved history-entry scroll state is used during history traversal instead of relying only on the live DOM scroll at the time the user clicks Back or Forward.
739
740
  - Unmarked scrollable containers may keep their outgoing scroll on push navigation so shared shells such as sidebars, rails, and docs nav panes stay stable across child-route changes.
740
- - `pp-reset-scroll="true"` on a scroll container opts that container into reset-on-navigation behavior. Use it on the main content pane of a grouped shell when page content should start at the top on each child-route navigation.
741
- - `pp-scroll-key="stable-name"` gives a scroll container a stable restoration identity. Prefer it when an element has no stable `id`, or when its classes or position can change between routes.
742
- - `body[pp-reset-scroll="true"]` is the global override for routes that should reset window scroll and every scrollable element.
741
+ - `pp-reset-scroll="true"` on a scroll container opts that container into reset-on-navigation behavior. Use it on the main content pane of a grouped shell when page content should start at the top on each child-route navigation.
742
+ - `pp-scroll-key="stable-name"` gives a scroll container a stable restoration identity. Prefer it when an element has no stable `id`, or when its classes or position can change between routes.
743
+ - `body[pp-reset-scroll="true"]` is the global override for routes that should reset window scroll and every scrollable element.
743
744
  - Navigation dispatches `pp:navigation:start`, `pp:navigation:complete`, and `pp:navigation:error` events on `document`.
744
745
 
745
746
  RPC notes:
@@ -881,9 +882,9 @@ These are current runtime caveats that matter for authors and AI tools:
881
882
  - Caspian already injects `pp-component` and rewrites owned scripts to `type="text/pp"` during render.
882
883
  - Nested roots without their own `script[type="text/pp"]` block are not fully isolated during parent template compilation.
883
884
  - The global `pp` singleton auto-mounts on DOM ready, and `pp.mount()` is idempotent.
884
- - `pp.effect` and `pp.layoutEffect` are cleanup-style hooks. Their callbacks are not promise-aware.
885
- - Callback refs may return synchronous cleanup functions, which run instead of a later `callback(null)` detach call.
886
- - `pp.context()` resolves through ancestor components, not the current component's own pending providers.
885
+ - `pp.effect` and `pp.layoutEffect` are cleanup-style hooks. Their callbacks are not promise-aware.
886
+ - Callback refs may return synchronous cleanup functions, which run instead of a later `callback(null)` detach call.
887
+ - `pp.context()` resolves through ancestor components, not the current component's own pending providers.
887
888
  - `pp.provideContext` is not part of the current runtime API. Use an HTML-first lowercase provider tag such as `<themecontext.provider>`.
888
889
  - `pp.portal()` preserves logical ancestry through the registry, so context and prop refresh behavior continue to work through portaled descendants.
889
890
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "caspian-utils",
3
- "version": "0.1.16",
3
+ "version": "0.1.17",
4
4
  "description": "Caspian tooling",
5
5
  "main": "index.js",
6
6
  "scripts": {