sliderpro-agentic-skills-etch 0.1.0 → 0.1.1

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.0",
3
+ "version": "0.1.1",
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": {
@@ -444,19 +444,28 @@ handler inside `ready()`: the slider mounted before your code ran, so it has alr
444
444
  Before configuring an unfamiliar slider, check whether it is a premade template. If it is, use
445
445
  that template's documented knobs rather than inventing new CSS.
446
446
 
447
- | Template | Identify by | Script | Guide |
448
- | --- | --- | --- | --- |
449
- | Slider Zeon | `.slider-zeon`, `.main-slider-zeon` | no | `https://design-with-cracka.gitbook.io/etchsliderpro/premade-templates` |
450
- | Slider Chronos | `.slider-chronos` | no | `https://design-with-cracka.gitbook.io/etchsliderpro/premade-templates` |
451
- | Slider Flow | `.slider-flow` | no | `https://design-with-cracka.gitbook.io/etchsliderpro/premade-templates` |
452
- | Slider Team | `.slider-team` | no | `https://design-with-cracka.gitbook.io/etchsliderpro/premade-templates` |
453
- | Slider Stack | `.slider-stack`, `.slider-stack__card` | no | `https://design-with-cracka.gitbook.io/etchsliderpro/card-stack-templates` |
454
- | Slider Marquee | no class prefix. Identify by the combination: Infinite Scroll on, Edge Fade on, Slide Auto Width on, two wrappers whose rows scroll in opposite directions | no | `https://design-with-cracka.gitbook.io/etchsliderpro/premade-templates` |
455
- | Deck Featured | `.deck-stack-featured`, `.deck-card-featured` | yes | `https://design-with-cracka.gitbook.io/etchsliderpro/card-stack-templates` |
456
- | Deck Testimonial | `.deck-stack-testimonial`, `.deck-card-testimonial` | yes | `https://design-with-cracka.gitbook.io/etchsliderpro/card-stack-templates` |
457
- | Fall | `.fall-stack`, `.fall-card` | yes | `https://design-with-cracka.gitbook.io/etchsliderpro/card-stack-templates` |
458
-
459
- All nine use Sync Custom Element.
447
+ Every template names its Wrapper, so one class on the Wrapper identifies all nine. Check that
448
+ first; the second column is confirmation.
449
+
450
+ | Template | Wrapper class | Also present | Script | Guide |
451
+ | --- | --- | --- | --- | --- |
452
+ | Slider Zeon | `.slider-zeon-wrapper` | `.slider-zeon__bg-thumb`, `.main-slider-zeon__content` | no | `https://design-with-cracka.gitbook.io/etchsliderpro/premade-templates` |
453
+ | Slider Chronos | `.slider-chronos-wrapper` | `.slider-chronos__slide`, `.slider-chronos__year` | no | `https://design-with-cracka.gitbook.io/etchsliderpro/premade-templates` |
454
+ | Slider Flow | `.slider-flow-wrapper` | `.slider-flow__slide`, `.slider-flow__slide-bg-media` | no | `https://design-with-cracka.gitbook.io/etchsliderpro/premade-templates` |
455
+ | Slider Team | `.slider-team-wrapper` | `.slider-team__grid`, `.slider-team__sync` | no | `https://design-with-cracka.gitbook.io/etchsliderpro/premade-templates` |
456
+ | Slider Stack | `.slider-stack-wrapper` | `.slider-stack__card`, `.slider-stack__card-lift` | no | `https://design-with-cracka.gitbook.io/etchsliderpro/card-stack-templates` |
457
+ | Slider Marquee | `.slider-marquee-wrapper` | two rows, Infinite Scroll on, Edge Fade on the Wrapper | no | `https://design-with-cracka.gitbook.io/etchsliderpro/premade-templates` |
458
+ | Deck Featured | `.slider-wrapper-deck-featured` | `.deck-stack-featured`, `.deck-card-featured` | yes | `https://design-with-cracka.gitbook.io/etchsliderpro/card-stack-templates` |
459
+ | Deck Testimonial | `.slider-wrapper-deck-testimonial` | `.deck-stack-testimonial`, `.deck-card-testimonial` | yes | `https://design-with-cracka.gitbook.io/etchsliderpro/card-stack-templates` |
460
+ | Fall | `.slider-wrapper-fall` | `.fall-stack`, `.fall-card` | yes | `https://design-with-cracka.gitbook.io/etchsliderpro/card-stack-templates` |
461
+
462
+ Note the two naming schemes: the six slider templates suffix the name (`.slider-flow-wrapper`),
463
+ the three card stacks infix it (`.slider-wrapper-fall`).
464
+
465
+ Five of the nine sync elements outside the track, and they do not all use the same prop. Team and
466
+ Stack set `sliderSetup.syncCustomElement` on the Slider; the three card stacks set
467
+ `sliderlessSync.customElement` on the Wrapper. Zeon pairs sliders by `sliderSetup.sliderRole`
468
+ instead, and Chronos, Flow and Marquee sync nothing.
460
469
 
461
470
  The three that carry a script expose named constants at the top of it. On the two Deck templates,
462
471
  `MAX_TIERS` is the deepest ring the CSS defines and `NAV_RINGS` is how many rings stay clickable.
@@ -147,20 +147,57 @@ await etch.saveAsync()
147
147
 
148
148
  ### Component instances are the unit of work
149
149
 
150
- A Slider Pro build is a tree of `etch/component` blocks, each carrying `ref` (the component id) and
151
- a flat `attributes` map of prop values:
150
+ A Slider Pro build is a tree of `etch/component` blocks, each naming a component and carrying a
151
+ flat `attributes` map of prop values. **Two different shapes describe the same tree, and mixing
152
+ them up is the first thing that goes wrong in a session.**
153
+
154
+ **The live shape**, which `etch.blocks.getTree()` returns and `etch.blocks.create()` accepts:
152
155
 
153
156
  ```json
154
157
  {
155
- "blockName": "etch/component",
156
- "attrs": {
157
- "metadata": { "name": "- Flow" },
158
- "ref": 6455,
159
- "attributes": { "wrapperHeight": "350px", "spaceBetweenSliders": "50px" }
160
- }
158
+ "type": "etch/component",
159
+ "version": 1,
160
+ "context": {},
161
+ "children": [],
162
+ "componentId": 6455,
163
+ "attributes": { "wrapperHeight": "350px", "spaceBetweenSliders": "50px" }
161
164
  }
162
165
  ```
163
166
 
167
+ `version`, `context` and `children` are required. Block ids are strings (`"ot2wnef"`), not numbers.
168
+
169
+ **The export shape**, which you only ever see inside a premade template `.json` file, uses
170
+ `blockName`, nests under `attrs`, and calls the component id `ref`:
171
+
172
+ ```json
173
+ { "blockName": "etch/component", "attrs": { "ref": 6455, "attributes": {} }, "innerBlocks": [] }
174
+ ```
175
+
176
+ Never pass the export shape to `create()`. It is rejected with
177
+ `Invalid block JSON: expected string, received undefined` at `path: ["type"]`. To put a template on
178
+ the page, hand its whole `gutenbergBlock` to `etch.blocks.pasteAsync()` instead.
179
+
180
+ ### Children go in a slot, never directly on the component
181
+
182
+ A component's children must be wrapped in an `etch/slot-content` node naming the slot they fill.
183
+ Putting a Slider straight inside a Wrapper's `children` renders nothing.
184
+
185
+ ```json
186
+ { "type": "etch/slot-content", "version": 1, "context": {}, "children": [], "slotName": "Slides" }
187
+ ```
188
+
189
+ | Component | Slots |
190
+ | --- | --- |
191
+ | DWC Slider Wrapper | `Sliders_and_Controls` |
192
+ | DWC Slider | `Top__Controls`, `Slides`, `Bottom__Controls` |
193
+ | DWC Slide | `Content` |
194
+ | DWC Slider Pagination | `PaginationButtons` |
195
+ | DWC Slider Nav Button | `Nav_Btn_Content` |
196
+ | DWC Slider Progress, DWC Slider Play-Pause | none |
197
+
198
+ Controls are siblings of the Slider inside `Sliders_and_Controls`, or children of the Slider's own
199
+ `Top__Controls` / `Bottom__Controls`. Both work, because controls find their own slider.
200
+
164
201
  ### Group props and the one-extra-brace rule
165
202
 
166
203
  Most Slider props live in groups (`layout`, `motion`, `slides`, `autoplay`, ...). A group is stored
@@ -305,9 +342,9 @@ unit. `props.pauseSlidersOnHover` on the Wrapper pauses both rows together.
305
342
 
306
343
  Infinite Scroll needs the Auto-Scroll extension enabled in admin settings, which is the default.
307
344
 
308
- ### Synced elements (Zeon, Chronos, Team)
345
+ ### Synced elements (Team, Stack)
309
346
 
310
- The pattern behind the full-bleed hero, the timeline and the staff showcase is one prop.
347
+ Driving arbitrary elements on the page from the slider is one prop.
311
348
 
312
349
  ```js
313
350
  setGroup(sliderId, 'sliderSetup', { syncCustomElement: '.timeline-node',
@@ -319,8 +356,23 @@ moves, and with nav on, clicking one jumps the slider to it. **You write the CSS
319
356
  states.** The elements do not need to be inside the slider and do not need to match the slide
320
357
  count.
321
358
 
359
+ The selector takes a comma-separated list, so one slider can drive several groups at once. Team
360
+ uses `'.slider-team__sync, .slider-team__sync-heading'` to move a portrait and a heading together.
361
+
322
362
  Grep `## 3. Sync Custom Element` in the reference for multiple selectors and the overlap caveat.
323
363
 
364
+ ### Main and thumbnails in one wrapper (Zeon)
365
+
366
+ A full-bleed hero with a thumbnail strip needs no sync prop at all, just roles:
367
+
368
+ ```js
369
+ setGroup(mainId, 'sliderSetup', { sliderRole: 'main', transitionType: 'Fade' });
370
+ setGroup(thumbId, 'sliderSetup', { sliderRole: 'thumbnails', transitionType: 'Loop' });
371
+ ```
372
+
373
+ Both inside the same Wrapper and they pair automatically. A Wrapper can hold more than one
374
+ thumbnail slider, which is how Zeon runs a background layer and a strip off the same main.
375
+
324
376
  ### Carousel on mobile, grid on desktop
325
377
 
326
378
  ```js
@@ -345,23 +397,51 @@ setGroup(wrapperId, 'sliderlessSync', {
345
397
 
346
398
  CSS handles the front card and its two neighbours from `is-active` / `is-prev` / `is-next`. What
347
399
  CSS cannot do is know that a given card is *three* back, so the rows behind, the z-index ladder and
348
- the click targets need a script. That is case 1 of the native-first gate. The shipped script does
349
- exactly three things:
400
+ the click targets need a script. That is case 1 of the native-first gate.
401
+
402
+ The contract between that script and the CSS is one attribute, **`data-pos`**, which the script
403
+ derives from `is-active` and writes on every card. It is a **signed** offset from the active card,
404
+ so the CSS can fan the left and right sides in opposite directions:
405
+
406
+ ```css
407
+ .deck-stack-featured &:is([data-pos='2'], [data-pos='-2']) { /* ring 2, both sides */ }
408
+ ```
409
+
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.
412
+
413
+ 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:
350
415
 
351
416
  ```js
352
417
  // 1. make a custom property interpolable, so a blur can animate (case 2)
353
418
  CSS.registerProperty({ name: '--stack-focus', syntax: '<number>',
354
419
  inherits: true, initialValue: '0' });
355
420
 
356
- // 2. per card: distance from the active one, capped at the deepest tier the CSS defines
357
- var rank = Math.abs(distanceFromActive);
358
- card.setAttribute('data-tier', Math.min(rank, MAX_TIERS));
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))));
359
424
 
360
- // 3. hit-testing: stack order by rank, and clicks off beyond the clickable rings
425
+ // 3. hit-testing: stack order by distance, and clicks off beyond the clickable rings
426
+ var rank = Math.abs(signed);
361
427
  card.style.zIndex = String(total - rank);
362
428
  lift.style.pointerEvents = rank <= NAV_RINGS ? 'auto' : 'none';
363
429
  ```
364
430
 
431
+ Recompute on every change: watch the stack with a `MutationObserver` filtered to `class`, since
432
+ `is-active` moving is the only signal you get.
433
+
434
+ ### Where a script goes
435
+
436
+ There is no script block type. Add a `script` element inside the wrapper:
437
+
438
+ ```js
439
+ el('script', {}, [ text(SOURCE) ])
440
+ ```
441
+
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.
444
+
365
445
  Step 3 is not optional. Stacked cards are coplanar, so the browser hit-tests them by DOM order and
366
446
  a click near the front card can land on one three positions away.
367
447
 
@@ -392,19 +472,30 @@ function setGroup(id, key, patch) {
392
472
  etch.blocks.setAttribute(id, key, '{' + JSON.stringify(next) + '}');
393
473
  }
394
474
 
395
- function component(ref, attributes, children) {
396
- return {
397
- blockName: 'etch/component',
398
- attrs: { ref: ref, attributes: attributes || {} },
399
- innerBlocks: children || []
400
- };
475
+ function node(extra, children) {
476
+ return Object.assign({ version: 1, context: {}, children: children || [] }, extra);
477
+ }
478
+
479
+ function component(componentId, attributes, children) {
480
+ return node({ type: 'etch/component', componentId: componentId,
481
+ attributes: attributes || {} }, children);
482
+ }
483
+
484
+ function slot(slotName, children) {
485
+ return node({ type: 'etch/slot-content', slotName: slotName }, children);
401
486
  }
402
487
 
403
- function findByRef(nodes, ref, out) {
488
+ function el(tag, attributes, children) {
489
+ return node({ type: 'etch/element', tag: tag, attributes: attributes || {} }, children);
490
+ }
491
+
492
+ function text(t) { return node({ type: 'etch/text', text: t }); }
493
+
494
+ function findByRef(nodes, componentId, out) {
404
495
  out = out || [];
405
496
  for (const n of nodes || []) {
406
- if (n.componentId === ref || (n.attrs && n.attrs.ref === ref)) out.push(n);
407
- findByRef(n.children || n.innerBlocks || [], ref, out);
497
+ if (n.componentId === componentId) out.push(n);
498
+ findByRef(n.children, componentId, out);
408
499
  }
409
500
  return out;
410
501
  }
@@ -415,18 +506,27 @@ function findByRef(nodes, ref, out) {
415
506
  ```js
416
507
  const C = comps();
417
508
  const slides = [];
418
- for (let i = 0; i < 5; i++) slides.push(component(C['DWC Slide'], {}));
509
+ for (let i = 0; i < 5; i++) {
510
+ slides.push(component(C['DWC Slide'], {}, [
511
+ slot('Content', [ el('div', {}, [ text('Slide ' + (i + 1)) ]) ])
512
+ ]));
513
+ }
419
514
 
420
515
  const id = etch.blocks.create(
421
516
  component(C['DWC Slider Wrapper'], {}, [
422
- component(C['DWC Slider'], {}, slides),
423
- component(C['DWC Slider Nav Button'], {}),
424
- component(C['DWC Slider Pagination'], {})
517
+ slot('Sliders_and_Controls', [
518
+ component(C['DWC Slider'], {}, [ slot('Slides', slides) ]),
519
+ component(C['DWC Slider Nav Button'], {}),
520
+ component(C['DWC Slider Pagination'], {})
521
+ ])
425
522
  ])
426
523
  );
427
524
  return id;
428
525
  ```
429
526
 
527
+ An empty Slide has no content and so no height. Give slides something to size before wondering why
528
+ the slider is a flat line.
529
+
430
530
  Build **one** first, screenshot it, then scale to the full count. Do not generate twenty slides
431
531
  before you have seen one render.
432
532