sliderpro-agentic-skills-etch 0.1.1 → 0.1.2

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sliderpro-agentic-skills-etch",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Installs the Slider Pro for Etch AI Connector skills files and component docs into any project",
5
5
  "type": "module",
6
6
  "bin": {
@@ -142,6 +142,9 @@ etch.blocks.create(json, parentId?, index?) // returns new id
142
142
  etch.components.list() // [{ id, name }, ...]
143
143
  etch.components.getJson(id) // .properties and .blocks
144
144
  etch.styles.list() // [{ id, selector, type, collection, css }]
145
+ etch.styles.create(selector, css) // returns a STYLE ID; pass it to a class prop
146
+ etch.blocks.addClass(blockId, name) // plain elements only; throws on a component
147
+ etch.blocks.getJson(id).script // { code }, the JavaScript code block
145
148
  await etch.saveAsync()
146
149
  ```
147
150
 
@@ -198,6 +201,47 @@ Putting a Slider straight inside a Wrapper's `children` renders nothing.
198
201
  Controls are siblings of the Slider inside `Sliders_and_Controls`, or children of the Slider's own
199
202
  `Top__Controls` / `Bottom__Controls`. Both work, because controls find their own slider.
200
203
 
204
+ ### Classes: two different mechanisms
205
+
206
+ Adding a class to a plain element and adding one to a component are **not the same operation**, and
207
+ the component path is the one that matters here, because everything Slider Pro ships is a component.
208
+
209
+ **On a component**, `addClass` throws `Block "<id>" is not an HTML block.` Classes go through the
210
+ component's own class-typed prop, and the value is the **style id**, not the class name:
211
+
212
+ ```js
213
+ const styleId = etch.styles.create('.flow-demo', 'border-radius: 1rem;'); // returns an id
214
+ etch.blocks.setAttribute(wrapperId, 'customClass', styleId);
215
+ ```
216
+
217
+ Etch resolves the id to the selector name when it renders, so the page gets
218
+ `class="dwc-slider-wrapper flow-demo"`. The id never appears in the output. Store the id, not the
219
+ name, so the class survives being renamed in the Etch UI.
220
+
221
+ The class-typed props, one per component:
222
+
223
+ | Component | Prop |
224
+ | --- | --- |
225
+ | DWC Slider Wrapper | `customClass` |
226
+ | DWC Slider | `sliderClass` |
227
+ | DWC Slide, Progress, Play-Pause, Pagination | `class` |
228
+ | DWC Slider Nav Button | `buttonClass`, `buttonWrapperClass` |
229
+
230
+ **On a plain element**, use `addClass` with the bare class name, no dot and no id:
231
+
232
+ ```js
233
+ const id = etch.blocks.create(el('article', {}, []));
234
+ etch.blocks.addClass(id, 'fall-card');
235
+ ```
236
+
237
+ Passing a style id here does not resolve. It is treated as a literal name and sanitised, so
238
+ `30xsolr` silently becomes the class `xsolr`. Creating the element with `attributes: { class: '...' }`
239
+ works too and is fine when you are building a subtree in one call.
240
+
241
+ Either way the CSS rule itself is `etch.styles.create('.fall-card', '...')`, which is what the
242
+ selector has to match.
243
+
244
+
201
245
  ### Group props and the one-extra-brace rule
202
246
 
203
247
  Most Slider props live in groups (`layout`, `motion`, `slides`, `autoplay`, ...). A group is stored
@@ -407,43 +451,79 @@ so the CSS can fan the left and right sides in opposite directions:
407
451
  .deck-stack-featured &:is([data-pos='2'], [data-pos='-2']) { /* ring 2, both sides */ }
408
452
  ```
409
453
 
410
- The stack container carries **`data-tiers`**, the number of rings the CSS defines, which lets the
411
- same CSS serve a three-ring fan and a one-ring stack.
454
+ The stack container carries **`data-tiers`**, how many rings are actually in play. It is computed,
455
+ not fixed: a looping deck needs spare cards to hide the wrap behind, so the script reduces the
456
+ tiers when there are too few cards.
412
457
 
413
458
  Writing an unsigned rank, or naming the attribute anything else, produces a flat pile: the rules
414
- above simply never match. The script does three things:
459
+ above simply never match. The shipped script does this:
415
460
 
416
461
  ```js
417
462
  // 1. make a custom property interpolable, so a blur can animate (case 2)
418
463
  CSS.registerProperty({ name: '--stack-focus', syntax: '<number>',
419
464
  inherits: true, initialValue: '0' });
420
465
 
421
- // 2. per card: SIGNED offset from the active card, clamped to the deepest ring
422
- var signed = index - activeIndex;
423
- card.setAttribute('data-pos', String(Math.max(-MAX_TIERS, Math.min(MAX_TIERS, signed))));
466
+ // 2. how many rings this deck can afford, given looping and the card count
467
+ var mayLoop = wrap.dataset.loop === 'true' && total >= MIN_LOOP;
468
+ stack.dataset.tiers = mayLoop ? Math.min(MAX_TIERS, Math.floor((total - 3) / 2)) : MAX_TIERS;
424
469
 
425
- // 3. hit-testing: stack order by distance, and clicks off beyond the clickable rings
426
- var rank = Math.abs(signed);
470
+ // 3. per card: SIGNED offset from the active card. On a looping deck the offset
471
+ // wraps, so the far end of the list reads as the near side, not as distance 8.
472
+ var d = n - active;
473
+ if (mayLoop) {
474
+ if (d > total / 2) d -= total;
475
+ if (d < -total / 2) d += total;
476
+ }
477
+ card.dataset.pos = d;
478
+
479
+ // 4. hit-testing: stack order by distance, and clicks off beyond the clickable rings
480
+ var rank = Math.abs(d);
427
481
  card.style.zIndex = String(total - rank);
428
482
  lift.style.pointerEvents = rank <= NAV_RINGS ? 'auto' : 'none';
429
483
  ```
430
484
 
485
+ Do not clamp `data-pos` to the tier count. Cards past the deepest ring should match no rule and
486
+ stay stacked at the back; clamping piles them onto the last visible ring instead.
487
+
488
+ Both decks also set `--i` on each line of card content so the CSS can stagger it:
489
+
490
+ ```js
491
+ card.querySelectorAll('.deck-card-featured__content > *')
492
+ .forEach(function (line, j) { line.style.setProperty('--i', j); });
493
+ ```
494
+
495
+ Step 4 is Deck only. **Fall's script is much smaller**: it sets `--i` and a signed `data-pos`, and
496
+ nothing else. Fall never loops, so there is no wrap to fold and no z-index ladder to maintain,
497
+ because the cards fall past each other rather than fanning around a front card.
498
+
431
499
  Recompute on every change: watch the stack with a `MutationObserver` filtered to `class`, since
432
500
  `is-active` moving is the only signal you get.
433
501
 
434
502
  ### Where a script goes
435
503
 
436
- There is no script block type. Add a `script` element inside the wrapper:
504
+ **Not in a `<script>` element.** Etch silently drops one from the render, so the page looks right
505
+ in the builder and ships with no behaviour at all.
506
+
507
+ Every block has an optional `script` field (`EtchBlockScript`), which is Etch's JavaScript code
508
+ block. Put the code on the **component instance that owns the markup**, which for a card stack is
509
+ the Wrapper:
437
510
 
438
511
  ```js
439
- el('script', {}, [ text(SOURCE) ])
512
+ const wrapperId = etch.blocks.create({
513
+ type: 'etch/component', version: 1, context: {}, children: [ /* ... */ ],
514
+ componentId: C['DWC Slider Wrapper'], attributes: {},
515
+ script: { code: "(function () { /* ... */ })();" }
516
+ });
440
517
  ```
441
518
 
442
- Component `<script>` elements are left alone on Sync Without Slider wrappers, which is why a deck
443
- script keeps working. Do not add one to a wrapper that contains a real slider and expect the same.
519
+ `code` is **plain source** over the API. The base64 you see in a premade template `.json` is only
520
+ how the export serialises it; do not encode it yourself.
521
+
522
+ Etch renders it as `<script type="module" defer>`, so it runs after parsing and top-level `await`
523
+ is available. Read it back with `etch.blocks.getJson(id).script`.
444
524
 
445
- Step 3 is not optional. Stacked cards are coplanar, so the browser hit-tests them by DOM order and
446
- a click near the front card can land on one three positions away.
525
+ Component scripts are also the reason a card deck keeps working: the bridge leaves Sync Without
526
+ Slider wrappers unreconstructed precisely so an author's script keeps observing the original nodes.
447
527
 
448
528
  Card counts for a looping deck: three are always visible (front plus two), and a loop needs a
449
529
  hidden slot at each end, so **five is the minimum** and nine gives the full three-row fan. Fall