@design-edito/tools 0.5.21 → 0.5.23

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.
Files changed (42) hide show
  1. package/agnostic/arrays/index.d.ts +1 -1
  2. package/agnostic/arrays/index.js +1 -1
  3. package/agnostic/colors/index.d.ts +3 -3
  4. package/agnostic/colors/index.js +3 -3
  5. package/agnostic/css/index.d.ts +2 -2
  6. package/agnostic/css/index.js +2 -2
  7. package/agnostic/errors/index.d.ts +1 -1
  8. package/agnostic/errors/index.js +1 -1
  9. package/agnostic/html/hyper-json/smart-tags/coalesced/index.d.ts +9 -9
  10. package/agnostic/html/hyper-json/smart-tags/coalesced/index.js +9 -9
  11. package/agnostic/html/index.d.ts +1 -1
  12. package/agnostic/html/index.js +1 -1
  13. package/agnostic/index.d.ts +5 -5
  14. package/agnostic/index.js +5 -5
  15. package/agnostic/misc/index.d.ts +2 -2
  16. package/agnostic/misc/index.js +2 -2
  17. package/agnostic/numbers/index.d.ts +1 -1
  18. package/agnostic/numbers/index.js +1 -1
  19. package/agnostic/random/index.d.ts +1 -1
  20. package/agnostic/random/index.js +1 -1
  21. package/components/Sequencer/index.d.ts +38 -7
  22. package/components/Sequencer/index.js +93 -8
  23. package/components/Sequencer/types.d.ts +57 -0
  24. package/components/Sequencer/types.js +32 -0
  25. package/components/Video/index.js +2 -1
  26. package/components/index.d.ts +1 -1
  27. package/components/index.js +1 -1
  28. package/node/@aws-s3/storage/directory/index.d.ts +1 -1
  29. package/node/@aws-s3/storage/directory/index.js +1 -1
  30. package/node/@aws-s3/storage/file/index.d.ts +2 -2
  31. package/node/@aws-s3/storage/file/index.js +2 -2
  32. package/node/@aws-s3/storage/index.d.ts +1 -1
  33. package/node/@aws-s3/storage/index.js +1 -1
  34. package/node/@google-cloud/storage/file/index.d.ts +1 -1
  35. package/node/@google-cloud/storage/file/index.js +1 -1
  36. package/node/ftps/file/index.d.ts +1 -1
  37. package/node/ftps/file/index.js +1 -1
  38. package/node/images/index.d.ts +1 -1
  39. package/node/images/index.js +1 -1
  40. package/node/images/transform/operations/index.d.ts +3 -3
  41. package/node/images/transform/operations/index.js +3 -3
  42. package/package.json +5 -1
@@ -1,6 +1,6 @@
1
1
  export * as dedupe from './dedupe/index.js'
2
2
  export * as findDuplicates from './find-duplicates/index.js'
3
- export * as isArrayOf from './is-array-of/index.js'
4
3
  export * as make from './make/index.js'
5
4
  export * as randomPick from './random-pick/index.js'
6
5
  export * as shuffle from './shuffle/index.js'
6
+ export * as isArrayOf from './is-array-of/index.js'
@@ -1,6 +1,6 @@
1
1
  export * as dedupe from './dedupe/index.js'
2
2
  export * as findDuplicates from './find-duplicates/index.js'
3
- export * as isArrayOf from './is-array-of/index.js'
4
3
  export * as make from './make/index.js'
5
4
  export * as randomPick from './random-pick/index.js'
6
5
  export * as shuffle from './shuffle/index.js'
6
+ export * as isArrayOf from './is-array-of/index.js'
@@ -1,12 +1,12 @@
1
1
  export * as channels from './channels/index.js'
2
2
  export * as contrast from './contrast/index.js'
3
3
  export * as convert from './convert/index.js'
4
- export * as distance from './distance/index.js'
5
4
  export * as grayscale from './grayscale/index.js'
6
- export * as invert from './invert/index.js'
5
+ export * as distance from './distance/index.js'
7
6
  export * as lerp from './lerp/index.js'
8
7
  export * as luminance from './luminance/index.js'
9
- export * as palette from './palette/index.js'
10
8
  export * as rotate from './rotate/index.js'
11
9
  export * as tidy from './tidy/index.js'
10
+ export * as invert from './invert/index.js'
12
11
  export * as typechecks from './typechecks/index.js'
12
+ export * as palette from './palette/index.js'
@@ -1,12 +1,12 @@
1
1
  export * as channels from './channels/index.js'
2
2
  export * as contrast from './contrast/index.js'
3
3
  export * as convert from './convert/index.js'
4
- export * as distance from './distance/index.js'
5
4
  export * as grayscale from './grayscale/index.js'
6
- export * as invert from './invert/index.js'
5
+ export * as distance from './distance/index.js'
7
6
  export * as lerp from './lerp/index.js'
8
7
  export * as luminance from './luminance/index.js'
9
- export * as palette from './palette/index.js'
10
8
  export * as rotate from './rotate/index.js'
11
9
  export * as tidy from './tidy/index.js'
10
+ export * as invert from './invert/index.js'
12
11
  export * as typechecks from './typechecks/index.js'
12
+ export * as palette from './palette/index.js'
@@ -1,6 +1,6 @@
1
1
  export * as bem from './bem/index.js'
2
2
  export * as clss from './clss/index.js'
3
- export * as generateNiceColor from './generate-nice-color/index.js'
4
- export * as scale from './scale/index.js'
5
3
  export * as isValidCssClassName from './is-valid-css-class-name/index.js'
4
+ export * as scale from './scale/index.js'
5
+ export * as generateNiceColor from './generate-nice-color/index.js'
6
6
  export * as stylesSet from './styles-set/index.js'
@@ -1,6 +1,6 @@
1
1
  export * as bem from './bem/index.js'
2
2
  export * as clss from './clss/index.js'
3
- export * as generateNiceColor from './generate-nice-color/index.js'
4
- export * as scale from './scale/index.js'
5
3
  export * as isValidCssClassName from './is-valid-css-class-name/index.js'
4
+ export * as scale from './scale/index.js'
5
+ export * as generateNiceColor from './generate-nice-color/index.js'
6
6
  export * as stylesSet from './styles-set/index.js'
@@ -1,2 +1,2 @@
1
- export * as register from './register/index.js'
2
1
  export * as unknownToString from './unknown-to-string/index.js'
2
+ export * as register from './register/index.js'
@@ -1,2 +1,2 @@
1
- export * as register from './register/index.js'
2
1
  export * as unknownToString from './unknown-to-string/index.js'
2
+ export * as register from './register/index.js'
@@ -1,28 +1,28 @@
1
1
  export * as add from './add/index.js'
2
2
  export * as addclass from './addclass/index.js'
3
3
  export * as and from './and/index.js'
4
- export * as append from './append/index.js'
5
4
  export * as at from './at/index.js'
5
+ export * as append from './append/index.js'
6
6
  export * as call from './call/index.js'
7
7
  export * as clone from './clone/index.js'
8
8
  export * as deleteproperties from './deleteproperties/index.js'
9
9
  export * as equals from './equals/index.js'
10
- export * as getattribute from './getattribute/index.js'
11
10
  export * as getproperties from './getproperties/index.js'
11
+ export * as getattribute from './getattribute/index.js'
12
12
  export * as getproperty from './getproperty/index.js'
13
- export * as hjparse from './hjparse/index.js'
14
13
  export * as hjstringify from './hjstringify/index.js'
15
14
  export * as if from './if/index.js'
16
15
  export * as initialize from './initialize/index.js'
16
+ export * as join from './join/index.js'
17
17
  export * as length from './length/index.js'
18
18
  export * as map from './map/index.js'
19
19
  export * as negate from './negate/index.js'
20
- export * as notrailing from './notrailing/index.js'
20
+ export * as hjparse from './hjparse/index.js'
21
21
  export * as or from './or/index.js'
22
+ export * as notrailing from './notrailing/index.js'
22
23
  export * as pickrandom from './pickrandom/index.js'
23
- export * as populate from './populate/index.js'
24
- export * as join from './join/index.js'
25
24
  export * as print from './print/index.js'
25
+ export * as populate from './populate/index.js'
26
26
  export * as push from './push/index.js'
27
27
  export * as pusheach from './pusheach/index.js'
28
28
  export * as recordtoarray from './recordtoarray/index.js'
@@ -30,8 +30,8 @@ export * as removeattribute from './removeattribute/index.js'
30
30
  export * as removeclass from './removeclass/index.js'
31
31
  export * as renameproperty from './renameproperty/index.js'
32
32
  export * as replace from './replace/index.js'
33
- export * as select from './select/index.js'
34
33
  export * as set from './set/index.js'
34
+ export * as select from './select/index.js'
35
35
  export * as setattribute from './setattribute/index.js'
36
36
  export * as setproperty from './setproperty/index.js'
37
37
  export * as sorton from './sorton/index.js'
@@ -41,12 +41,12 @@ export * as toarray from './toarray/index.js'
41
41
  export * as toboolean from './toboolean/index.js'
42
42
  export * as toelement from './toelement/index.js'
43
43
  export * as toggleclass from './toggleclass/index.js'
44
- export * as tonodelist from './tonodelist/index.js'
45
44
  export * as tonull from './tonull/index.js'
45
+ export * as tonodelist from './tonodelist/index.js'
46
46
  export * as tonumber from './tonumber/index.js'
47
47
  export * as torecord from './torecord/index.js'
48
48
  export * as toref from './toref/index.js'
49
49
  export * as tostring from './tostring/index.js'
50
50
  export * as totext from './totext/index.js'
51
- export * as transformselected from './transformselected/index.js'
52
51
  export * as trim from './trim/index.js'
52
+ export * as transformselected from './transformselected/index.js'
@@ -1,28 +1,28 @@
1
1
  export * as add from './add/index.js'
2
2
  export * as addclass from './addclass/index.js'
3
3
  export * as and from './and/index.js'
4
- export * as append from './append/index.js'
5
4
  export * as at from './at/index.js'
5
+ export * as append from './append/index.js'
6
6
  export * as call from './call/index.js'
7
7
  export * as clone from './clone/index.js'
8
8
  export * as deleteproperties from './deleteproperties/index.js'
9
9
  export * as equals from './equals/index.js'
10
- export * as getattribute from './getattribute/index.js'
11
10
  export * as getproperties from './getproperties/index.js'
11
+ export * as getattribute from './getattribute/index.js'
12
12
  export * as getproperty from './getproperty/index.js'
13
- export * as hjparse from './hjparse/index.js'
14
13
  export * as hjstringify from './hjstringify/index.js'
15
14
  export * as if from './if/index.js'
16
15
  export * as initialize from './initialize/index.js'
16
+ export * as join from './join/index.js'
17
17
  export * as length from './length/index.js'
18
18
  export * as map from './map/index.js'
19
19
  export * as negate from './negate/index.js'
20
- export * as notrailing from './notrailing/index.js'
20
+ export * as hjparse from './hjparse/index.js'
21
21
  export * as or from './or/index.js'
22
+ export * as notrailing from './notrailing/index.js'
22
23
  export * as pickrandom from './pickrandom/index.js'
23
- export * as populate from './populate/index.js'
24
- export * as join from './join/index.js'
25
24
  export * as print from './print/index.js'
25
+ export * as populate from './populate/index.js'
26
26
  export * as push from './push/index.js'
27
27
  export * as pusheach from './pusheach/index.js'
28
28
  export * as recordtoarray from './recordtoarray/index.js'
@@ -30,8 +30,8 @@ export * as removeattribute from './removeattribute/index.js'
30
30
  export * as removeclass from './removeclass/index.js'
31
31
  export * as renameproperty from './renameproperty/index.js'
32
32
  export * as replace from './replace/index.js'
33
- export * as select from './select/index.js'
34
33
  export * as set from './set/index.js'
34
+ export * as select from './select/index.js'
35
35
  export * as setattribute from './setattribute/index.js'
36
36
  export * as setproperty from './setproperty/index.js'
37
37
  export * as sorton from './sorton/index.js'
@@ -41,12 +41,12 @@ export * as toarray from './toarray/index.js'
41
41
  export * as toboolean from './toboolean/index.js'
42
42
  export * as toelement from './toelement/index.js'
43
43
  export * as toggleclass from './toggleclass/index.js'
44
- export * as tonodelist from './tonodelist/index.js'
45
44
  export * as tonull from './tonull/index.js'
45
+ export * as tonodelist from './tonodelist/index.js'
46
46
  export * as tonumber from './tonumber/index.js'
47
47
  export * as torecord from './torecord/index.js'
48
48
  export * as toref from './toref/index.js'
49
49
  export * as tostring from './tostring/index.js'
50
50
  export * as totext from './totext/index.js'
51
- export * as transformselected from './transformselected/index.js'
52
51
  export * as trim from './trim/index.js'
52
+ export * as transformselected from './transformselected/index.js'
@@ -1,5 +1,4 @@
1
1
  export * as deepSelect from './deep-select/index.js'
2
- export * as getNodeAncestors from './get-node-ancestors/index.js'
3
2
  export * as getPositionInsideParent from './get-position-inside-parent/index.js'
4
3
  export * as hyperJson from './hyper-json/index.js'
5
4
  export * as insertNode from './insert-node/index.js'
@@ -8,3 +7,4 @@ export * as replaceInElement from './replace-in-element/index.js'
8
7
  export * as selectorToElement from './selector-to-element/index.js'
9
8
  export * as stringToNodes from './string-to-nodes/index.js'
10
9
  export * as watchSelection from './watch-selection/index.js'
10
+ export * as getNodeAncestors from './get-node-ancestors/index.js'
@@ -1,5 +1,4 @@
1
1
  export * as deepSelect from './deep-select/index.js'
2
- export * as getNodeAncestors from './get-node-ancestors/index.js'
3
2
  export * as getPositionInsideParent from './get-position-inside-parent/index.js'
4
3
  export * as hyperJson from './hyper-json/index.js'
5
4
  export * as insertNode from './insert-node/index.js'
@@ -8,3 +7,4 @@ export * as replaceInElement from './replace-in-element/index.js'
8
7
  export * as selectorToElement from './selector-to-element/index.js'
9
8
  export * as stringToNodes from './string-to-nodes/index.js'
10
9
  export * as watchSelection from './watch-selection/index.js'
10
+ export * as getNodeAncestors from './get-node-ancestors/index.js'
@@ -1,17 +1,17 @@
1
1
  export * as arrays from './arrays/index.js'
2
- export * as colors from './colors/index.js'
3
2
  export * as booleans from './booleans/index.js'
4
- export * as css from './css/index.js'
3
+ export * as colors from './colors/index.js'
5
4
  export * as errors from './errors/index.js'
6
- export * as html from './html/index.js'
5
+ export * as css from './css/index.js'
7
6
  export * as misc from './misc/index.js'
8
7
  export * as objects from './objects/index.js'
8
+ export * as html from './html/index.js'
9
9
  export * as optim from './optim/index.js'
10
- export * as numbers from './numbers/index.js'
11
10
  export * as random from './random/index.js'
12
11
  export * as regexps from './regexps/index.js'
13
- export * as sanitization from './sanitization/index.js'
14
12
  export * as strings from './strings/index.js'
13
+ export * as sanitization from './sanitization/index.js'
15
14
  export * as subtitles from './subtitles/index.js'
16
15
  export * as time from './time/index.js'
17
16
  export * as typescript from './typescript/index.js'
17
+ export * as numbers from './numbers/index.js'
package/agnostic/index.js CHANGED
@@ -1,17 +1,17 @@
1
1
  export * as arrays from './arrays/index.js'
2
- export * as colors from './colors/index.js'
3
2
  export * as booleans from './booleans/index.js'
4
- export * as css from './css/index.js'
3
+ export * as colors from './colors/index.js'
5
4
  export * as errors from './errors/index.js'
6
- export * as html from './html/index.js'
5
+ export * as css from './css/index.js'
7
6
  export * as misc from './misc/index.js'
8
7
  export * as objects from './objects/index.js'
8
+ export * as html from './html/index.js'
9
9
  export * as optim from './optim/index.js'
10
- export * as numbers from './numbers/index.js'
11
10
  export * as random from './random/index.js'
12
11
  export * as regexps from './regexps/index.js'
13
- export * as sanitization from './sanitization/index.js'
14
12
  export * as strings from './strings/index.js'
13
+ export * as sanitization from './sanitization/index.js'
15
14
  export * as subtitles from './subtitles/index.js'
16
15
  export * as time from './time/index.js'
17
16
  export * as typescript from './typescript/index.js'
17
+ export * as numbers from './numbers/index.js'
@@ -2,11 +2,11 @@ export * as assert from './assert/index.js'
2
2
  export * as cast from './cast/index.js'
3
3
  export * as connection from './connection/index.js'
4
4
  export * as crawler from './crawler/index.js'
5
- export * as crossenv from './crossenv/index.js'
6
5
  export * as dataSize from './data-size/index.js'
6
+ export * as crossenv from './crossenv/index.js'
7
7
  export * as isConstructorFunction from './is-constructor-function/index.js'
8
8
  export * as isNullish from './is-nullish/index.js'
9
- export * as loremIpsum from './lorem-ipsum/index.js'
10
9
  export * as logs from './logs/index.js'
10
+ export * as loremIpsum from './lorem-ipsum/index.js'
11
11
  export * as normalizeExtension from './normalize-extension/index.js'
12
12
  export * as outcome from './outcome/index.js'
@@ -2,11 +2,11 @@ export * as assert from './assert/index.js'
2
2
  export * as cast from './cast/index.js'
3
3
  export * as connection from './connection/index.js'
4
4
  export * as crawler from './crawler/index.js'
5
- export * as crossenv from './crossenv/index.js'
6
5
  export * as dataSize from './data-size/index.js'
6
+ export * as crossenv from './crossenv/index.js'
7
7
  export * as isConstructorFunction from './is-constructor-function/index.js'
8
8
  export * as isNullish from './is-nullish/index.js'
9
- export * as loremIpsum from './lorem-ipsum/index.js'
10
9
  export * as logs from './logs/index.js'
10
+ export * as loremIpsum from './lorem-ipsum/index.js'
11
11
  export * as normalizeExtension from './normalize-extension/index.js'
12
12
  export * as outcome from './outcome/index.js'
@@ -1,6 +1,6 @@
1
1
  export * as absoluteModulo from './absolute-modulo/index.js'
2
2
  export * as approximateRational from './approximate-rational/index.js'
3
- export * as clamp from './clamp/index.js'
4
3
  export * as geometricProgressions from './geometric-progressions/index.js'
5
4
  export * as interpolate from './interpolate/index.js'
5
+ export * as clamp from './clamp/index.js'
6
6
  export * as round from './round/index.js'
@@ -1,6 +1,6 @@
1
1
  export * as absoluteModulo from './absolute-modulo/index.js'
2
2
  export * as approximateRational from './approximate-rational/index.js'
3
- export * as clamp from './clamp/index.js'
4
3
  export * as geometricProgressions from './geometric-progressions/index.js'
5
4
  export * as interpolate from './interpolate/index.js'
5
+ export * as clamp from './clamp/index.js'
6
6
  export * as round from './round/index.js'
@@ -1,3 +1,3 @@
1
+ export * as hexChar from './hex-char/index.js'
1
2
  export * as random from './random/index.js'
2
3
  export * as uuid from './uuid/index.js'
3
- export * as hexChar from './hex-char/index.js'
@@ -1,3 +1,3 @@
1
+ export * as hexChar from './hex-char/index.js'
1
2
  export * as random from './random/index.js'
2
3
  export * as uuid from './uuid/index.js'
3
- export * as hexChar from './hex-char/index.js'
@@ -1,5 +1,7 @@
1
1
  import { type FunctionComponent, type PropsWithChildren } from 'react';
2
2
  import type { WithClassName } from '../utils/types.js';
3
+ import type { ViewportBehaviours } from '../utils/viewport-behaviours/types.js';
4
+ import type { SequencerAction } from './types.js';
3
5
  /**
4
6
  * @property totalSteps - How many steps the sequence has. Falls back to the number of
5
7
  * **element** children: text and whitespace never count, which matters more than it
@@ -13,9 +15,16 @@ import type { WithClassName } from '../utils/types.js';
13
15
  * @property step - The position, taken over by the consumer. Provided, the tempo stops
14
16
  * advancing anything: the counter is theirs.
15
17
  * @property defaultStep - The position to start from. Ignored when `step` is provided.
16
- * @property play - Whether the sequence advances. **There are no controls in this
17
- * component** — nothing to click, so nothing to surrender to — and this is the only way
18
- * it moves on its own.
18
+ * @property play - Whether the sequence advances, taken over by the consumer. Provided,
19
+ * it is the whole answer and the instructions no longer reach it, the way `step` takes
20
+ * the counter over from the tempo.
21
+ * @property defaultPlay - Whether it starts advancing. `false` by default, and the
22
+ * starting point a `'play'` instruction moves from — not a setting, hence `default…`.
23
+ * @property behavioursSuspended - Holds back the instructions that **start** something,
24
+ * and lets through those that stop it. For a consumer withholding the sequence behind
25
+ * something — a warning to accept, typically. What was held back is replayed the moment
26
+ * this goes false, so lifting the veil on an already-visible sequence does what was
27
+ * asked. `':force'` does not override it.
19
28
  * @property tempo - Speed in beats per minute: one step every `60000 / tempo` ms, so `60`
20
29
  * is a step per second. Clamped to a minimum of `1`.
21
30
  * @property loop - Whether the sequence wraps round. **`false` by default**, so a
@@ -24,11 +33,15 @@ import type { WithClassName } from '../utils/types.js';
24
33
  * active step it resolves to. Never on mount.
25
34
  * @property onIsPlayingChanged - Called once the effective play state changed — which
26
35
  * includes it dropping to `false` on its own at the end.
27
- * @property onIsEndedChanged - Called when the sequence reaches its last step, or leaves
28
- * it. A looping sequence never ends, so never emits.
36
+ * @property onIsEndedChanged - Called when the sequence ends, or leaves that state.
37
+ * **The end is the counter leaving the last step, not arriving on it** — the last step
38
+ * is owed its beat like every other one, and a sequence paused on it has not ended. A
39
+ * looping sequence never ends, so never emits.
29
40
  * @property onLooped - Called on each wrap, only while `loop` is `true`.
30
41
  * @property onReachedFirstStep - Called when the position becomes `0`.
31
- * @property onReachedLastStep - Called when the position becomes the last one.
42
+ * @property onReachedLastStep - Called when the position becomes the last one. This is
43
+ * the arrival, where `onIsEndedChanged` is the departure: on a playing sequence they are
44
+ * one beat apart.
32
45
  */
33
46
  export type Props = PropsWithChildren<WithClassName<{
34
47
  totalSteps?: number;
@@ -36,6 +49,7 @@ export type Props = PropsWithChildren<WithClassName<{
36
49
  step?: number;
37
50
  defaultStep?: number;
38
51
  play?: boolean;
52
+ defaultPlay?: boolean;
39
53
  tempo?: number;
40
54
  loop?: boolean;
41
55
  onStepChanged?: (step: number, activeStep: number) => void;
@@ -44,7 +58,9 @@ export type Props = PropsWithChildren<WithClassName<{
44
58
  onLooped?: () => void;
45
59
  onReachedFirstStep?: () => void;
46
60
  onReachedLastStep?: () => void;
47
- }>>;
61
+ }>> & ViewportBehaviours<SequencerAction> & {
62
+ behavioursSuspended?: boolean;
63
+ };
48
64
  /**
49
65
  * A sequencer over its children, which it classifies and never moves.
50
66
  *
@@ -59,6 +75,21 @@ export type Props = PropsWithChildren<WithClassName<{
59
75
  * Children that are not elements — text, whitespace — are rendered untouched and take no
60
76
  * part: they carry no class, so they simply stay visible throughout.
61
77
  *
78
+ * @remarks
79
+ * **Viewport-driven behaviour is declared, not named by a prop.** `whenVisible` and
80
+ * `whenHidden` take a verb or a list of them, out of {@link SequencerAction} — `'play'`,
81
+ * `'jump-start'`, `'jump-by:1'` — each optionally suffixed by `':once'` and `':force'`.
82
+ * The old `playOnVisible`, `pauseOnHidden`, `resetOnVisible` and `resetOnHidden` are
83
+ * those four instructions written the long way: `whenHidden={['pause', 'jump-start']}`
84
+ * is the pair of them, and the order of a list is the order of execution. See
85
+ * `components/utils/viewport-behaviours` for the grammar, and the `visibility…` props
86
+ * for what « visible » means and how long it has to have been true.
87
+ *
88
+ * **Nothing surrenders here.** The layer lets a reader's hand switch an instruction off
89
+ * for the rest of the mount, and this component has no control for a hand to touch — so
90
+ * `':force'` has nothing to override, and the single `'playback'` domain is a formality.
91
+ * A gate still holds `'play'` back, which is a different brake. @see {@link SequencerDomain}
92
+ *
62
93
  * ### On the root
63
94
  * `--playing`, `--at-start`, `--at-end`, `--ended`, plus `data-step`, `data-active-step`,
64
95
  * `data-total-steps` and `data-tempo`.
@@ -1,9 +1,10 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { Children, cloneElement, isValidElement, useEffect, useState } from 'react';
2
+ import { Children, cloneElement, isValidElement, useEffect, useRef, useState } from 'react';
3
3
  import { absoluteModulo } from '../../agnostic/numbers/absolute-modulo/index.js';
4
4
  import { clamp } from '../../agnostic/numbers/clamp/index.js';
5
5
  import { clss } from '../../agnostic/css/clss/index.js';
6
6
  import { mergeClassNames, useChangeDispatch } from '../utils/index.js';
7
+ import { useViewportBehaviours } from '../utils/viewport-behaviours/index.js';
7
8
  import { sequencer as publicClassName } from '../public-classnames.js';
8
9
  import cssModule from './styles.module.css';
9
10
  /**
@@ -57,6 +58,21 @@ function stepsOf(child, elementIndex) {
57
58
  * Children that are not elements — text, whitespace — are rendered untouched and take no
58
59
  * part: they carry no class, so they simply stay visible throughout.
59
60
  *
61
+ * @remarks
62
+ * **Viewport-driven behaviour is declared, not named by a prop.** `whenVisible` and
63
+ * `whenHidden` take a verb or a list of them, out of {@link SequencerAction} — `'play'`,
64
+ * `'jump-start'`, `'jump-by:1'` — each optionally suffixed by `':once'` and `':force'`.
65
+ * The old `playOnVisible`, `pauseOnHidden`, `resetOnVisible` and `resetOnHidden` are
66
+ * those four instructions written the long way: `whenHidden={['pause', 'jump-start']}`
67
+ * is the pair of them, and the order of a list is the order of execution. See
68
+ * `components/utils/viewport-behaviours` for the grammar, and the `visibility…` props
69
+ * for what « visible » means and how long it has to have been true.
70
+ *
71
+ * **Nothing surrenders here.** The layer lets a reader's hand switch an instruction off
72
+ * for the rest of the mount, and this component has no control for a hand to touch — so
73
+ * `':force'` has nothing to override, and the single `'playback'` domain is a formality.
74
+ * A gate still holds `'play'` back, which is a different brake. @see {@link SequencerDomain}
75
+ *
60
76
  * ### On the root
61
77
  * `--playing`, `--at-start`, `--at-end`, `--ended`, plus `data-step`, `data-active-step`,
62
78
  * `data-total-steps` and `data-tempo`.
@@ -73,9 +89,11 @@ function stepsOf(child, elementIndex) {
73
89
  * therefore `--is-first` at 1 and `--not-first` at 6, and the answer is the same on every
74
90
  * lap without anything being reset.
75
91
  */
76
- export const Sequencer = ({ totalSteps, stepMap, step, defaultStep, play, tempo = 60, loop, onStepChanged, onIsPlayingChanged, onIsEndedChanged, onLooped, onReachedFirstStep, onReachedLastStep, className, children }) => {
92
+ export const Sequencer = ({ totalSteps, stepMap, step, defaultStep, play, defaultPlay, tempo = 60, loop, onStepChanged, onIsPlayingChanged, onIsEndedChanged, onLooped, onReachedFirstStep, onReachedLastStep, behavioursSuspended, visibilityThreshold, visibilityRoot, visibilityRootMargin, visibilityOnAfterMs, visibilityOffAfterMs, whenVisible, whenHidden, onVisibilityChanged, className, children }) => {
77
93
  const [internalStep, setInternalStep] = useState(step ?? defaultStep ?? 0);
94
+ const [internalPlay, setInternalPlay] = useState(defaultPlay ?? false);
78
95
  const [hasLapped, setHasLapped] = useState(0);
96
+ const rootRef = useRef(null);
79
97
  // Children, split once: what takes part and what merely renders.
80
98
  const childrenArr = Children.toArray(children);
81
99
  const elements = childrenArr.filter(isValidElement);
@@ -88,11 +106,14 @@ export const Sequencer = ({ totalSteps, stepMap, step, defaultStep, play, tempo
88
106
  : clamp(rawStep, 0, stepsCount - 1))
89
107
  : 0;
90
108
  const activeStep = stepMap?.[position] ?? position;
91
- // A sequence that does not loop stops on its last step, and says so rather than
92
- // claiming to still be playing. Derived rather than held: nothing has to be unset when
93
- // `loop` or `step` changes under it.
94
- const isEnded = loop !== true && stepsCount > 0 && position >= stepsCount - 1;
95
- const isPlaying = (play ?? false) && !isEnded;
109
+ // **The end is the counter leaving the last step, not arriving on it.** The last step
110
+ // is owed its beat like every other one, so the counter runs one past the end while
111
+ // the position clamps to it — which is also what keeps the whole thing derived: nothing
112
+ // has to be unset when `loop` or `step` changes under it, and `onReachedLastStep` stays
113
+ // the arrival that this is not. A sequence merely paused on the last step has not
114
+ // ended, and a consumer driving `step` says so by naming the position after the last.
115
+ const isEnded = loop !== true && stepsCount > 0 && rawStep >= stepsCount;
116
+ const isPlaying = (play ?? internalPlay) && !isEnded;
96
117
  useEffect(() => {
97
118
  if (!isPlaying || step !== undefined || stepsCount <= 0)
98
119
  return;
@@ -110,6 +131,70 @@ export const Sequencer = ({ totalSteps, stepMap, step, defaultStep, play, tempo
110
131
  setHasLapped(lap);
111
132
  onLooped?.();
112
133
  }, [lap, loop]);
134
+ // Viewport behaviours
135
+ // A jump names a position and lands on it **within the current lap**: the counter is
136
+ // absolute, so setting it to a bare position on a looping sequence would count as a
137
+ // wrap backwards and fire `onLooped` for a move nobody made. `jump-by` is left alone
138
+ // on purpose — stepping past the last position really is a wrap, and says so.
139
+ const jumpToPosition = (target) => {
140
+ if (step !== undefined || stepsCount <= 0)
141
+ return;
142
+ const resolved = target < 0 ? stepsCount + target : target;
143
+ const bounded = loop === true
144
+ ? absoluteModulo(resolved, stepsCount)
145
+ : clamp(resolved, 0, stepsCount - 1);
146
+ setInternalStep(lap * stepsCount + bounded);
147
+ };
148
+ const jumpBy = (offset) => {
149
+ if (step !== undefined || stepsCount <= 0)
150
+ return;
151
+ setInternalStep(current => current + offset);
152
+ };
153
+ // What each verb does. Rebuilt on every render — it closes over the setters — which is
154
+ // why the generic layer reads it through a ref rather than a dependency list.
155
+ //
156
+ // `play` and `pause` need no guard against a controlled `play`: the effective state
157
+ // reads the prop first, so the internal one they write is simply never consulted.
158
+ const actions = {
159
+ play: { kind: 'start', domain: 'playback', run: () => setInternalPlay(true) },
160
+ pause: { kind: 'stop', domain: 'playback', run: () => setInternalPlay(false) },
161
+ // A jump starts nothing on its own — it moves a counter, playing or not — so a gate
162
+ // has no reason to hold it back.
163
+ 'jump-to': {
164
+ kind: 'stop',
165
+ domain: 'playback',
166
+ run: arg => {
167
+ const target = Number(arg);
168
+ if (!Number.isFinite(target))
169
+ return;
170
+ jumpToPosition(target);
171
+ }
172
+ },
173
+ 'jump-start': { kind: 'stop', domain: 'playback', run: () => jumpToPosition(0) },
174
+ 'jump-end': { kind: 'stop', domain: 'playback', run: () => jumpToPosition(-1) },
175
+ 'jump-by': {
176
+ kind: 'stop',
177
+ domain: 'playback',
178
+ run: arg => {
179
+ const offset = Number(arg);
180
+ if (!Number.isFinite(offset))
181
+ return;
182
+ jumpBy(offset);
183
+ }
184
+ }
185
+ };
186
+ // The surrender half of the result is dropped, and that is the whole of what this
187
+ // component's lack of controls changes: nothing here can be taken over by hand.
188
+ useViewportBehaviours(rootRef, {
189
+ visibilityThreshold,
190
+ visibilityRoot,
191
+ visibilityRootMargin,
192
+ visibilityOnAfterMs,
193
+ visibilityOffAfterMs,
194
+ whenVisible,
195
+ whenHidden,
196
+ onVisibilityChanged
197
+ }, actions, behavioursSuspended === true);
113
198
  // State dispatch
114
199
  useChangeDispatch(position, () => onStepChanged?.(position, activeStep));
115
200
  useChangeDispatch(isPlaying, onIsPlayingChanged);
@@ -137,7 +222,7 @@ export const Sequencer = ({ totalSteps, stepMap, step, defaultStep, play, tempo
137
222
  return positions;
138
223
  };
139
224
  let elementIndex = -1;
140
- return _jsx("div", { className: rootClss, "data-step": position, "data-active-step": activeStep, "data-total-steps": stepsCount, "data-tempo": tempo, children: childrenArr.map((child, childPos) => {
225
+ return _jsx("div", { ref: rootRef, className: rootClss, "data-step": position, "data-active-step": activeStep, "data-total-steps": stepsCount, "data-tempo": tempo, children: childrenArr.map((child, childPos) => {
141
226
  if (!isValidElement(child))
142
227
  return child;
143
228
  elementIndex += 1;
@@ -0,0 +1,57 @@
1
+ /**
2
+ * The verbs a sequence answers to, as the table keys them.
3
+ *
4
+ * `jump-to` and `jump-by` are the two taking an argument, and the table is keyed by the
5
+ * verb alone — the argument is parsed out of the instruction before the lookup.
6
+ *
7
+ * The family is `Video`'s, word for word: a sequence and a player move a counter, and
8
+ * two vocabularies for that one gesture is exactly what the viewport-behaviours layer
9
+ * exists to stop. `jump-start` is the old `resetOnVisible` under the shared name.
10
+ */
11
+ export declare const SEQUENCER_VERBS: readonly ["play", "pause", "jump-to", "jump-start", "jump-end", "jump-by"];
12
+ export type SequencerVerb = typeof SEQUENCER_VERBS[number];
13
+ /**
14
+ * How to read the argument of each verb that takes one.
15
+ *
16
+ * **Exported because a consumer has to validate what it is handed**, and a type gives a
17
+ * runtime validator nothing to compare against: lm-link reads an article's props out of
18
+ * static XML and has to reject `'jump-to:banana'` before it reaches the component.
19
+ *
20
+ * A digit string, and deliberately not `Number`: that would take `'1e3'` and `'0x10'`,
21
+ * which nobody means to write in an article.
22
+ */
23
+ export declare const SEQUENCER_VERB_ARGUMENTS: {
24
+ readonly 'jump-to': (arg: string) => boolean;
25
+ readonly 'jump-by': (arg: string) => boolean;
26
+ };
27
+ /**
28
+ * The instructions a consumer writes in `whenVisible` / `whenHidden`.
29
+ *
30
+ * **A jump names a position, never an active step** — the counter, the thing `step` and
31
+ * `defaultStep` already name. What that position *means* stays `stepMap`'s answer, which
32
+ * is the one place the component's two numbers could be confused for one another.
33
+ *
34
+ * `'jump-to:2'` goes to position 2, and **a negative value counts from the end**:
35
+ * `'jump-to:-1'` is the last position, `-1` rather than `-0` because `-0 === 0` in
36
+ * JavaScript and would collide with the start. `'jump-start'` and `'jump-end'` are the
37
+ * shorthands for `'jump-to:0'` and `'jump-to:-1'`.
38
+ *
39
+ * `'jump-by:1'` is the next position and `'jump-by:-1'` the previous one — signed and
40
+ * relative, where `jump-to` is absolute. The two forms of `-1` therefore do not say the
41
+ * same thing, which is the price of keeping one family rather than adding `next` and
42
+ * `prev` beside it.
43
+ *
44
+ * Every one of them takes the `':once'` and `':force'` suffixes, which are the generic
45
+ * layer's and are not restated here.
46
+ */
47
+ export type SequencerAction = Exclude<SequencerVerb, 'jump-to' | 'jump-by'> | `jump-to:${number}` | `jump-by:${number}`;
48
+ /**
49
+ * What a verb competes with — one domain, and it is a formality.
50
+ *
51
+ * **This component has no controls**: nothing to click, so nothing a reader can take
52
+ * over and nothing that ever surrenders. The field is part of {@link ActionSpec} and is
53
+ * declared honestly rather than split into domains no hand could ever tell apart. The
54
+ * consequence is that `':force'` has no trigger here — it overrides a surrender, and
55
+ * there are none.
56
+ */
57
+ export type SequencerDomain = 'playback';
@@ -0,0 +1,32 @@
1
+ /**
2
+ * The verbs a sequence answers to, as the table keys them.
3
+ *
4
+ * `jump-to` and `jump-by` are the two taking an argument, and the table is keyed by the
5
+ * verb alone — the argument is parsed out of the instruction before the lookup.
6
+ *
7
+ * The family is `Video`'s, word for word: a sequence and a player move a counter, and
8
+ * two vocabularies for that one gesture is exactly what the viewport-behaviours layer
9
+ * exists to stop. `jump-start` is the old `resetOnVisible` under the shared name.
10
+ */
11
+ export const SEQUENCER_VERBS = [
12
+ 'play',
13
+ 'pause',
14
+ 'jump-to',
15
+ 'jump-start',
16
+ 'jump-end',
17
+ 'jump-by'
18
+ ];
19
+ /**
20
+ * How to read the argument of each verb that takes one.
21
+ *
22
+ * **Exported because a consumer has to validate what it is handed**, and a type gives a
23
+ * runtime validator nothing to compare against: lm-link reads an article's props out of
24
+ * static XML and has to reject `'jump-to:banana'` before it reaches the component.
25
+ *
26
+ * A digit string, and deliberately not `Number`: that would take `'1e3'` and `'0x10'`,
27
+ * which nobody means to write in an article.
28
+ */
29
+ export const SEQUENCER_VERB_ARGUMENTS = {
30
+ 'jump-to': (arg) => /^-?\d+$/v.test(arg),
31
+ 'jump-by': (arg) => /^-?\d+$/v.test(arg)
32
+ };
@@ -137,7 +137,8 @@ export const Video = ({ defaultSubtitlesOn = true, behavioursSuspended, visibili
137
137
  const handleFullscreenChange = useCallback((isFullscreen) => {
138
138
  if (!isFullscreen)
139
139
  setFullscreen(false);
140
- }, []);
140
+ controlledProps.onFullscreenChange?.(isFullscreen);
141
+ }, [controlledProps.onFullscreenChange]);
141
142
  const handleOnLoadedMetadataEvent = useCallback((e) => {
142
143
  muteAttributeWorkaround(e.currentTarget, controlledProps.muted ?? false);
143
144
  controlledProps.onLoadedMetadata?.(e);
@@ -13,8 +13,8 @@ export * as jsonEditor from './JsonEditor/index.js'
13
13
  export * as lightbox from './Lightbox/index.js'
14
14
  export * as listLoader from './ListLoader/index.js'
15
15
  export * as overlayer from './Overlayer/index.js'
16
- export * as paginator from './Paginator/index.js'
17
16
  export * as resizeObserver from './ResizeObserver/index.js'
17
+ export * as paginator from './Paginator/index.js'
18
18
  export * as scrllgngn from './Scrllgngn/index.js'
19
19
  export * as scrollListener from './ScrollListener/index.js'
20
20
  export * as select from './Select/index.js'
@@ -13,8 +13,8 @@ export * as jsonEditor from './JsonEditor/index.js'
13
13
  export * as lightbox from './Lightbox/index.js'
14
14
  export * as listLoader from './ListLoader/index.js'
15
15
  export * as overlayer from './Overlayer/index.js'
16
- export * as paginator from './Paginator/index.js'
17
16
  export * as resizeObserver from './ResizeObserver/index.js'
17
+ export * as paginator from './Paginator/index.js'
18
18
  export * as scrllgngn from './Scrllgngn/index.js'
19
19
  export * as scrollListener from './ScrollListener/index.js'
20
20
  export * as select from './Select/index.js'
@@ -1,4 +1,4 @@
1
1
  export * as copyDir from './copy-dir/index.js'
2
- export * as list from './list/index.js'
3
2
  export * as moveDir from './move-dir/index.js'
3
+ export * as list from './list/index.js'
4
4
  export * as removeDir from './remove-dir/index.js'
@@ -1,4 +1,4 @@
1
1
  export * as copyDir from './copy-dir/index.js'
2
- export * as list from './list/index.js'
3
2
  export * as moveDir from './move-dir/index.js'
3
+ export * as list from './list/index.js'
4
4
  export * as removeDir from './remove-dir/index.js'
@@ -1,7 +1,7 @@
1
1
  export * as copy from './copy/index.js'
2
2
  export * as download from './download/index.js'
3
3
  export * as exists from './exists/index.js'
4
- export * as move from './move/index.js'
5
4
  export * as remove from './remove/index.js'
6
- export * as stat from './stat/index.js'
5
+ export * as move from './move/index.js'
7
6
  export * as upload from './upload/index.js'
7
+ export * as stat from './stat/index.js'
@@ -1,7 +1,7 @@
1
1
  export * as copy from './copy/index.js'
2
2
  export * as download from './download/index.js'
3
3
  export * as exists from './exists/index.js'
4
- export * as move from './move/index.js'
5
4
  export * as remove from './remove/index.js'
6
- export * as stat from './stat/index.js'
5
+ export * as move from './move/index.js'
7
6
  export * as upload from './upload/index.js'
7
+ export * as stat from './stat/index.js'
@@ -1,2 +1,2 @@
1
- export * as file from './file/index.js'
2
1
  export * as directory from './directory/index.js'
2
+ export * as file from './file/index.js'
@@ -1,2 +1,2 @@
1
- export * as file from './file/index.js'
2
1
  export * as directory from './directory/index.js'
2
+ export * as file from './file/index.js'
@@ -3,9 +3,9 @@ export * as download from './download/index.js'
3
3
  export * as exists from './exists/index.js'
4
4
  export * as generateSignedUrl from './generate-signed-url/index.js'
5
5
  export * as getMetadata from './get-metadata/index.js'
6
- export * as getPermissions from './get-permissions/index.js'
7
6
  export * as move from './move/index.js'
8
7
  export * as remove from './remove/index.js'
8
+ export * as getPermissions from './get-permissions/index.js'
9
9
  export * as revokeSignedUrls from './revoke-signed-urls/index.js'
10
10
  export * as stat from './stat/index.js'
11
11
  export * as updateMetadata from './update-metadata/index.js'
@@ -3,9 +3,9 @@ export * as download from './download/index.js'
3
3
  export * as exists from './exists/index.js'
4
4
  export * as generateSignedUrl from './generate-signed-url/index.js'
5
5
  export * as getMetadata from './get-metadata/index.js'
6
- export * as getPermissions from './get-permissions/index.js'
7
6
  export * as move from './move/index.js'
8
7
  export * as remove from './remove/index.js'
8
+ export * as getPermissions from './get-permissions/index.js'
9
9
  export * as revokeSignedUrls from './revoke-signed-urls/index.js'
10
10
  export * as stat from './stat/index.js'
11
11
  export * as updateMetadata from './update-metadata/index.js'
@@ -1,6 +1,6 @@
1
1
  export * as copy from './copy/index.js'
2
- export * as download from './download/index.js'
3
2
  export * as exists from './exists/index.js'
3
+ export * as download from './download/index.js'
4
4
  export * as move from './move/index.js'
5
5
  export * as remove from './remove/index.js'
6
6
  export * as stat from './stat/index.js'
@@ -1,6 +1,6 @@
1
1
  export * as copy from './copy/index.js'
2
- export * as download from './download/index.js'
3
2
  export * as exists from './exists/index.js'
3
+ export * as download from './download/index.js'
4
4
  export * as move from './move/index.js'
5
5
  export * as remove from './remove/index.js'
6
6
  export * as stat from './stat/index.js'
@@ -1,5 +1,5 @@
1
- export * as create from './create/index.js'
2
1
  export * as format from './format/index.js'
3
2
  export * as metadata from './metadata/index.js'
4
3
  export * as transform from './transform/index.js'
5
4
  export * as utils from './utils/index.js'
5
+ export * as create from './create/index.js'
@@ -1,5 +1,5 @@
1
- export * as create from './create/index.js'
2
1
  export * as format from './format/index.js'
3
2
  export * as metadata from './metadata/index.js'
4
3
  export * as transform from './transform/index.js'
5
4
  export * as utils from './utils/index.js'
5
+ export * as create from './create/index.js'
@@ -1,15 +1,15 @@
1
1
  export * as blur from './blur/index.js'
2
2
  export * as brighten from './brighten/index.js'
3
3
  export * as extend from './extend/index.js'
4
- export * as extract from './extract/index.js'
5
4
  export * as flatten from './flatten/index.js'
5
+ export * as extract from './extract/index.js'
6
6
  export * as flip from './flip/index.js'
7
- export * as flop from './flop/index.js'
8
7
  export * as hue from './hue/index.js'
8
+ export * as flop from './flop/index.js'
9
9
  export * as level from './level/index.js'
10
10
  export * as lighten from './lighten/index.js'
11
11
  export * as normalize from './normalize/index.js'
12
- export * as overlay from './overlay/index.js'
13
12
  export * as resize from './resize/index.js'
14
13
  export * as rotate from './rotate/index.js'
14
+ export * as overlay from './overlay/index.js'
15
15
  export * as saturate from './saturate/index.js'
@@ -1,15 +1,15 @@
1
1
  export * as blur from './blur/index.js'
2
2
  export * as brighten from './brighten/index.js'
3
3
  export * as extend from './extend/index.js'
4
- export * as extract from './extract/index.js'
5
4
  export * as flatten from './flatten/index.js'
5
+ export * as extract from './extract/index.js'
6
6
  export * as flip from './flip/index.js'
7
- export * as flop from './flop/index.js'
8
7
  export * as hue from './hue/index.js'
8
+ export * as flop from './flop/index.js'
9
9
  export * as level from './level/index.js'
10
10
  export * as lighten from './lighten/index.js'
11
11
  export * as normalize from './normalize/index.js'
12
- export * as overlay from './overlay/index.js'
13
12
  export * as resize from './resize/index.js'
14
13
  export * as rotate from './rotate/index.js'
14
+ export * as overlay from './overlay/index.js'
15
15
  export * as saturate from './saturate/index.js'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@design-edito/tools",
3
- "version": "0.5.21",
3
+ "version": "0.5.23",
4
4
  "description": "",
5
5
  "author": "Maxime Fabas",
6
6
  "license": "ISC",
@@ -1558,6 +1558,10 @@
1558
1558
  "./components/Sequencer/index.js": {
1559
1559
  "import": "./components/Sequencer/index.js"
1560
1560
  },
1561
+ "./components/Sequencer/types.js": {
1562
+ "import": "./components/Sequencer/types.js",
1563
+ "types": "./components/Sequencer/types.d.ts"
1564
+ },
1561
1565
  "./components/ShadowRoot": {
1562
1566
  "import": "./components/ShadowRoot/index.js",
1563
1567
  "types": "./components/ShadowRoot/index.d.ts"