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
|
@@ -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`**,
|
|
411
|
-
|
|
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
|
|
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.
|
|
422
|
-
var
|
|
423
|
-
|
|
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.
|
|
426
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
443
|
-
|
|
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
|
-
|
|
446
|
-
|
|
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
|