presently 0.9.0 → 0.11.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7e8ef82aede27b4db4d147618230f5138e0ed0e1d09b3db25e1f42a82e4b6d5f
4
- data.tar.gz: 672e37fb2a6d0c8e098feaf2e9e2cf4c46818688f56593b3bf6bec4b1b60121a
3
+ metadata.gz: 4d9c48a214f82231e41cf7466a9cacae0b613d966df0ba2e2ed3ec0a5e770fd6
4
+ data.tar.gz: 5adf796d7508e530e7bcd29158db6090f48020987e17cf708f788fa2cfeafbcb
5
5
  SHA512:
6
- metadata.gz: d68b6edccc103dab053927144fc2c5e9ebed7e9ca94c3fb45a827e87861cb5d7b2521e676e63e03df0943925fbedbba45c0f235339bef0905090dfd43e740e5f
7
- data.tar.gz: 36c1daa240c0d6f8c1260525952922652b34538077b7deb64929eb08dd7ac1debd75abcb98eb00d62f59af3b6637bddfa2c5bb4b4666e511c3c859657b7d71df
6
+ metadata.gz: 33dc185804e859fee50a41d7169f12c8c7a0921789c9a561db4d03fb0ac172c51680a41f07e59df01232b9d1221a3cc50587c7731ce987e87ba6c858bb79e552
7
+ data.tar.gz: a36e22c1b6919eb78795364eb251107913e334b90dc60cdb874b6ca10aef71b6639a51d17c4453893da21cc687882d01649acdc7517ff69692d7c93e32272f1b
checksums.yaml.gz.sig CHANGED
Binary file
@@ -5,5 +5,5 @@
5
5
 
6
6
  # @namespace
7
7
  module Presently
8
- VERSION = "0.9.0"
8
+ VERSION = "0.11.0"
9
9
  end
data/public/slide.js CHANGED
@@ -154,32 +154,76 @@ export class SlideElements {
154
154
  }
155
155
  }
156
156
 
157
- // Returned by Slide#after to enable relative delay chaining.
158
- // Each .after(delay, callback) fires that many milliseconds after the previous step.
159
- class SlideChain {
157
+ // Scoped scripting context used both for chaining after() calls and as the
158
+ // argument passed to slide.loop() callbacks. Accumulates elapsed time across
159
+ // after() calls so each delay is relative to the previous step. Delegates
160
+ // find() and setTimeout() to the parent Slide so element queries are scoped
161
+ // correctly and all timeouts are cancelled automatically on slide change.
162
+ export class SlideContext {
160
163
  #slide;
161
164
  #elapsed;
162
165
 
163
- constructor(slide, elapsed) {
166
+ constructor(slide, elapsed = 0) {
164
167
  this.#slide = slide;
165
168
  this.#elapsed = elapsed;
166
169
  }
167
170
 
171
+ // The slide body element.
172
+ // Delegates to the parent Slide.
173
+ // @returns [HTMLElement]
174
+ get element() {
175
+ return this.#slide.element;
176
+ }
177
+
178
+ // Find elements within the slide matching the given CSS selector.
179
+ // Delegates to the parent Slide.
180
+ // @parameter selector [String] A CSS selector scoped to the slide body.
181
+ // @returns [SlideElements]
182
+ find(selector) {
183
+ return this.#slide.find(selector);
184
+ }
185
+
186
+ // Tracked setTimeout — delegates to the parent Slide so timeouts are
187
+ // cancelled automatically when the slide changes.
188
+ // @parameter callback [Function] The function to call after the delay.
189
+ // @parameter delay [Number] Delay in milliseconds.
190
+ // @returns [Number] The timeout ID.
191
+ setTimeout(callback, delay) {
192
+ return this.#slide.setTimeout(callback, delay);
193
+ }
194
+
195
+ // Schedule a callback relative to the previous step, accumulating elapsed time.
196
+ // @parameter delay [Number] Delay in milliseconds after the previous step.
197
+ // @parameter callback [Function] The function to call.
198
+ // @returns [SlideContext]
168
199
  after(delay, callback) {
169
200
  this.#elapsed += delay;
170
201
  this.#slide.setTimeout(callback, this.#elapsed);
171
202
  return this;
172
203
  }
204
+
205
+ // Total time accumulated across all after() calls.
206
+ // Used by slide.loop() to know when to schedule the next iteration.
207
+ // @returns [Number] Elapsed time in milliseconds.
208
+ get elapsed() {
209
+ return this.#elapsed;
210
+ }
173
211
  }
174
212
 
175
213
  // The scripting context passed to each slide's javascript block.
176
214
  // Scopes element queries to the slide body.
177
215
  export class Slide {
178
- #container;
216
+ #element;
179
217
  #timeouts = [];
180
218
 
181
- constructor(container) {
182
- this.#container = container;
219
+ constructor(element) {
220
+ this.#element = element;
221
+ }
222
+
223
+ // The slide body element.
224
+ // @returns [HTMLElement]
225
+ get element() {
226
+ return this.#element;
183
227
  }
184
228
 
185
229
  // Find elements within this slide matching the given CSS selector.
@@ -187,7 +231,7 @@ export class Slide {
187
231
  // @parameter selector [String] A CSS selector scoped to the slide body.
188
232
  // @returns [SlideElements]
189
233
  find(selector) {
190
- const elements = Array.from(this.#container.querySelectorAll(selector));
234
+ const elements = Array.from(this.#element.querySelectorAll(selector));
191
235
  return new SlideElements(this, elements);
192
236
  }
193
237
 
@@ -202,15 +246,30 @@ export class Slide {
202
246
  return timeoutId;
203
247
  }
204
248
 
205
- // Schedule a callback after a delay, returning a chainable object so
249
+ // Schedule a callback after a delay, returning a SlideContext so
206
250
  // subsequent .after(delay) calls are relative to the previous step.
207
251
  // All timeouts are tracked and cancelled automatically on slide change.
208
- // @parameter delay [Number] Delay in milliseconds from now (or previous step).
252
+ // @parameter delay [Number] Delay in milliseconds from now.
209
253
  // @parameter callback [Function] The function to call after the delay.
210
- // @returns [SlideChain]
254
+ // @returns [SlideContext]
211
255
  after(delay, callback) {
212
256
  this.setTimeout(callback, delay);
213
- return new SlideChain(this, delay);
257
+ return new SlideContext(this, delay);
258
+ }
259
+
260
+ // Run a callback in a loop, repeating indefinitely until the slide changes.
261
+ // The callback receives a SlideContext so it can use after() to schedule
262
+ // steps within each iteration. The loop waits for all steps to complete
263
+ // (ctx.elapsed) plus an optional extra delay before starting the next iteration.
264
+ // @parameter callback [Function] Receives a fresh SlideContext as `context` each iteration.
265
+ // @parameter delay [Number] Extra pause in milliseconds after the last step before restarting.
266
+ loop(callback, { delay = 0 } = {}) {
267
+ const iterate = () => {
268
+ const context = new SlideContext(this);
269
+ callback(context);
270
+ this.setTimeout(iterate, context.elapsed + delay);
271
+ };
272
+ iterate();
214
273
  }
215
274
 
216
275
  // Cancel all pending timeouts registered by this slide's script.
data/readme.md CHANGED
@@ -29,6 +29,15 @@ Please see the [project documentation](https://socketry.github.io/presently/) fo
29
29
 
30
30
  Please see the [project releases](https://socketry.github.io/presently/releases/index) for all releases.
31
31
 
32
+ ### v0.11.0
33
+
34
+ - Add `Slide#element` and `SlideContext#element` getters — expose the slide body DOM element directly for cases where `find()` is not sufficient, such as measuring dimensions, attaching event listeners, or integrating third-party libraries.
35
+
36
+ ### v0.10.0
37
+
38
+ - Replace internal `SlideChain` with an exported `SlideContext` class. `SlideContext` accumulates elapsed time across `after()` calls exactly as `SlideChain` did, but also exposes `find()`, `setTimeout()`, and a `get elapsed()` getter. `Slide#after()` now returns a `SlideContext` — existing slide scripts are unaffected.
39
+ - Add `Slide#loop(callback, {delay})` — runs a callback in a repeating loop until the slide changes. The callback receives a fresh `SlideContext` each iteration so it can schedule steps with `after()`. The loop waits for all steps to complete (`context.elapsed`) plus an optional extra `delay` before starting the next iteration. All timeouts flow through the slide's existing tracked `setTimeout`, so they are cancelled automatically on slide change.
40
+
32
41
  ### v0.9.0
33
42
 
34
43
  - `SlideBuilder#show` and `SlideBuilder#next` no longer overwrite `view-transition-name` on elements that already have one set. This allows elements with explicit names (for morph transitions to other slides) to coexist with the build system — they still get `visibility` and `viewTransitionClass` managed, but keep their own name.
@@ -81,17 +90,6 @@ Please see the [project releases](https://socketry.github.io/presently/releases/
81
90
  - Use the last `---` hrule in the AST as the presenter notes separator, so earlier `---` dividers in slide content are preserved correctly.
82
91
  - Add support for Mermaid diagrams in slides.
83
92
 
84
- ### v0.1.0
85
-
86
- - Initial release.
87
- - Slide files are Markdown with YAML front matter for metadata (`template`, `duration`, `title`, `skip`, `marker`, `transition`, `focus`).
88
- - Slide content is split into named sections by top-level headings, rendered to HTML via Markly.
89
- - Presenter notes are separated from slide content by a `---` divider.
90
- - Magic move transitions between slides.
91
- - Navigation control in the presenter view.
92
- - Code highlighting with line-range focus support.
93
- - Live state synchronisation between display and presenter views over WebSockets.
94
-
95
93
  ## See Also
96
94
 
97
95
  - [lively](https://github.com/socketry/lively) — The real-time application framework that powers Presently.
data/releases.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Releases
2
2
 
3
+ ## v0.11.0
4
+
5
+ - Add `Slide#element` and `SlideContext#element` getters — expose the slide body DOM element directly for cases where `find()` is not sufficient, such as measuring dimensions, attaching event listeners, or integrating third-party libraries.
6
+
7
+ ## v0.10.0
8
+
9
+ - Replace internal `SlideChain` with an exported `SlideContext` class. `SlideContext` accumulates elapsed time across `after()` calls exactly as `SlideChain` did, but also exposes `find()`, `setTimeout()`, and a `get elapsed()` getter. `Slide#after()` now returns a `SlideContext` — existing slide scripts are unaffected.
10
+ - Add `Slide#loop(callback, {delay})` — runs a callback in a repeating loop until the slide changes. The callback receives a fresh `SlideContext` each iteration so it can schedule steps with `after()`. The loop waits for all steps to complete (`context.elapsed`) plus an optional extra `delay` before starting the next iteration. All timeouts flow through the slide's existing tracked `setTimeout`, so they are cancelled automatically on slide change.
11
+
3
12
  ## v0.9.0
4
13
 
5
14
  - `SlideBuilder#show` and `SlideBuilder#next` no longer overwrite `view-transition-name` on elements that already have one set. This allows elements with explicit names (for morph transitions to other slides) to coexist with the build system — they still get `visibility` and `viewTransitionClass` managed, but keep their own name.
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: presently
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
metadata.gz.sig CHANGED
Binary file