@wix/editor-react-components 1.2747.0 → 1.2749.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.
- package/dist/site/components/VideoScrub/timeframes/TimeframeLayer.d.ts +22 -0
- package/dist/site/components/VideoScrub/timeframes/edit.d.ts +86 -0
- package/dist/site/components/VideoScrub/timeframes/index.d.ts +13 -0
- package/dist/site/components/VideoScrub/timeframes/parse.d.ts +26 -0
- package/dist/site/components/VideoScrub/timeframes/query.d.ts +7 -0
- package/dist/site/components/VideoScrub/timeframes/timeframeId.d.ts +5 -0
- package/dist/site/components/VideoScrub/timeframes/types.d.ts +64 -0
- package/dist/site/components/VideoScrub/timeframes/useActiveTimeframeIndex.d.ts +8 -0
- package/dist/site/components/VideoScrub/timeframes/validate.d.ts +17 -0
- package/dist/site/components/VideoScrub/timeframes/watchVideoTime.d.ts +7 -0
- package/package.json +3 -3
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { default as React, AriaAttributes, ReactNode } from 'react';
|
|
2
|
+
export type TimeframeLayerItem = {
|
|
3
|
+
/** The timeframe's `timeframeIdentifier` (runtime props have no `_id`). Never the index: that would mix up container state after a split. */
|
|
4
|
+
key: string;
|
|
5
|
+
content: ReactNode;
|
|
6
|
+
};
|
|
7
|
+
export type TimeframeLayerProps = {
|
|
8
|
+
/** Same order as the timeframes. */
|
|
9
|
+
items: ReadonlyArray<TimeframeLayerItem>;
|
|
10
|
+
activeIndex: number | undefined;
|
|
11
|
+
className?: string;
|
|
12
|
+
/**
|
|
13
|
+
* The layer's label, from the parent's `a11y` data (already converted with
|
|
14
|
+
* `convertA11yKeysToHtmlFormat`). Focus falls back to the layer, so it needs a name.
|
|
15
|
+
*/
|
|
16
|
+
a11yAttributes?: AriaAttributes;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Shows the active timeframe's content on top of the video. All items stay mounted (the inactive
|
|
20
|
+
* ones hidden) on purpose: the server HTML then holds every timeframe's content, for SEO.
|
|
21
|
+
*/
|
|
22
|
+
export declare function TimeframeLayer({ items, activeIndex, className, a11yAttributes, }: TimeframeLayerProps): React.JSX.Element;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { Timeframe, NewTimeframe, Result, NewTimeframeId, Rules } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* One timeframe from 0 to DEFAULT_TIMEFRAME_MS (or the whole video if it is shorter), with a new
|
|
4
|
+
* timeframeIdentifier. No container key, so the editor makes an empty one. A video shorter than
|
|
5
|
+
* MIN_LENGTH_MS has room for no timeframe, so the list is empty.
|
|
6
|
+
*/
|
|
7
|
+
export declare function createInitial(durationMs: number, { newTimeframeId, }?: {
|
|
8
|
+
newTimeframeId?: NewTimeframeId;
|
|
9
|
+
}): Array<NewTimeframe>;
|
|
10
|
+
/**
|
|
11
|
+
* A new timeframe that starts at `atMs`, in a gap. Its length is DEFAULT_TIMEFRAME_MS, or less when
|
|
12
|
+
* the next timeframe or the end of the video comes first. It fails with insideTimeframe when `atMs`
|
|
13
|
+
* is inside a timeframe (a timeframe's own end is not inside it), and with noRoom when less than
|
|
14
|
+
* MIN_LENGTH_MS fits. No container key, so the editor makes an empty one.
|
|
15
|
+
* `result.index` is the new timeframe's position.
|
|
16
|
+
*/
|
|
17
|
+
export declare function add(list: ReadonlyArray<Timeframe>, atMs: number, rules: Rules): Result;
|
|
18
|
+
/** Cuts the timeframe that contains `atMs` in two. In a gap it fails with inGap. */
|
|
19
|
+
export declare function split(list: ReadonlyArray<Timeframe>, atMs: number, rules: Rules): Result;
|
|
20
|
+
export type Edge = 'start' | 'end';
|
|
21
|
+
/**
|
|
22
|
+
* Drags one edge of `list[index]` to `atMs`. Moving into a gap changes only this timeframe. When the
|
|
23
|
+
* edge reaches a neighbor, it keeps pushing: the neighbor's touching edge moves too, so the
|
|
24
|
+
* neighbor gets shorter. It never pushes past one neighbor. It fails with tooShort when this
|
|
25
|
+
* timeframe or the neighbor would be under MIN_LENGTH_MS; use edgeLimits to clamp a drag first.
|
|
26
|
+
*/
|
|
27
|
+
export declare function resizeEdge(list: ReadonlyArray<Timeframe>, index: number, edge: Edge, atMs: number, rules: Rules): Result;
|
|
28
|
+
/**
|
|
29
|
+
* The range `resizeEdge` accepts for one edge: this timeframe and the neighbor it may push both keep
|
|
30
|
+
* MIN_LENGTH_MS, and the edge stays inside `[0, durationMs]`. Undefined for an unknown index.
|
|
31
|
+
* On broken saved data `minMs` can be more than `maxMs`: then no drag is possible.
|
|
32
|
+
*/
|
|
33
|
+
export declare function edgeLimits(list: ReadonlyArray<Timeframe>, index: number, edge: Edge, rules: Rules): {
|
|
34
|
+
minMs: number;
|
|
35
|
+
maxMs: number;
|
|
36
|
+
} | undefined;
|
|
37
|
+
/**
|
|
38
|
+
* The `startMs` range `moveTimeframe` can reach for `list[index]`, keeping its length. It may push
|
|
39
|
+
* every timeframe before it to 0 and every timeframe after it to durationMs, so: from the total
|
|
40
|
+
* length of the timeframes before it, to durationMs minus its own length and the total length of
|
|
41
|
+
* the timeframes after it. Gaps do not count, because a push uses them up. Undefined for an unknown
|
|
42
|
+
* index. On broken saved data (timeframes longer than the video) `minMs` can be more than `maxMs`.
|
|
43
|
+
*/
|
|
44
|
+
export declare function moveLimits(list: ReadonlyArray<Timeframe>, index: number, rules: Rules): {
|
|
45
|
+
minMs: number;
|
|
46
|
+
maxMs: number;
|
|
47
|
+
} | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* Moves the whole timeframe `list[index]` so it starts at `startMs`, keeping its length. When it
|
|
50
|
+
* reaches a neighbor it pushes it, and that neighbor pushes the next one, as a chain: each pushed
|
|
51
|
+
* timeframe keeps its length, gaps are used up first, and a timeframe moves only when it is reached.
|
|
52
|
+
* `startMs` is clamped to moveLimits, so the last pushed timeframe stops at 0 or at durationMs.
|
|
53
|
+
* The order never changes and `result.index` is `index`. Only times change; `_id`,
|
|
54
|
+
* `timeframeIdentifier`, `name` and `container` stay. Errors: notFound, badTime (not a whole
|
|
55
|
+
* number), and the usual result checks (on broken saved data, see moveLimits).
|
|
56
|
+
*/
|
|
57
|
+
export declare function moveTimeframe(list: ReadonlyArray<Timeframe>, index: number, startMs: number, rules: Rules): Result;
|
|
58
|
+
/**
|
|
59
|
+
* Removes a timeframe and leaves a gap: no neighbor gets its time. Removing the only timeframe is
|
|
60
|
+
* fine (an empty list is valid). `result.index` is the position the removed item had, moved back
|
|
61
|
+
* by one when it was last, so it points at a neighbor; it is -1 when the list is now empty.
|
|
62
|
+
* It does not check the result: it works on a broken list, so users can repair old data.
|
|
63
|
+
* Run validate on result.list to see the problems that are still there.
|
|
64
|
+
*/
|
|
65
|
+
export declare function remove(list: ReadonlyArray<Timeframe>, _id: string): Result;
|
|
66
|
+
type TimeframePatch = {
|
|
67
|
+
name?: string | undefined;
|
|
68
|
+
/** `null` removes it, back to the default (1). */
|
|
69
|
+
scrollSensitivity?: number | null | undefined;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Changes only `name` and `scrollSensitivity`; an undefined value keeps the old one. Times change
|
|
73
|
+
* only through add, split, resizeEdge, moveTimeframe and remove. A name that is not a string fails
|
|
74
|
+
* with badItem (validate checks it; the editor crashes on it). Two items with this _id fail with
|
|
75
|
+
* duplicateId.
|
|
76
|
+
*/
|
|
77
|
+
export declare function update(list: ReadonlyArray<Timeframe>, _id: string, patch: TimeframePatch, rules: Rules): Result;
|
|
78
|
+
/**
|
|
79
|
+
* A guard for a video length that is a little off (the 1 ms rounding of ms → s → ms). Any timeframe
|
|
80
|
+
* that ends past `rules.durationMs` is cut to end there. It never resets and never makes a timeframe
|
|
81
|
+
* longer: a longer video just has a gap at the end. It drops nothing: an item that starts at or
|
|
82
|
+
* after `durationMs` is a tooShort error, and so is an item that would get under MIN_LENGTH_MS.
|
|
83
|
+
* An empty list comes back as it is. The result is checked like every other write.
|
|
84
|
+
*/
|
|
85
|
+
export declare function fitToDuration(list: ReadonlyArray<Timeframe>, rules: Rules): Result;
|
|
86
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type { Timeframe, TimeframeError, TimeframeErrorCode, TimeframeTiming, NewTimeframe, NewTimeframeId, Result, Rules, } from './types';
|
|
2
|
+
export { DEFAULT_TIMEFRAME_MS, MAX_COUNT, MIN_LENGTH_MS } from './types';
|
|
3
|
+
export { parseList, toMs } from './parse';
|
|
4
|
+
export type { ParsedList } from './parse';
|
|
5
|
+
export { createTimeframeId } from './timeframeId';
|
|
6
|
+
export { validate } from './validate';
|
|
7
|
+
export { add, createInitial, edgeLimits, fitToDuration, moveTimeframe, moveLimits, remove, resizeEdge, split, update, } from './edit';
|
|
8
|
+
export type { Edge } from './edit';
|
|
9
|
+
export { activeAt } from './query';
|
|
10
|
+
export { watchVideoTime } from './watchVideoTime';
|
|
11
|
+
export { useActiveTimeframeIndex } from './useActiveTimeframeIndex';
|
|
12
|
+
export { TimeframeLayer } from './TimeframeLayer';
|
|
13
|
+
export type { TimeframeLayerItem, TimeframeLayerProps } from './TimeframeLayer';
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Timeframe, TimeframeError, NewTimeframeId } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Video seconds to whole milliseconds, rounded down. A non-finite input gives NaN.
|
|
4
|
+
* The tiny 1e-6 keeps exact ms safe through ms → s → ms: 8.033 * 1000 is 8032.999… in floating point.
|
|
5
|
+
*/
|
|
6
|
+
export declare const toMs: (seconds: number) => number;
|
|
7
|
+
export type ParsedList = {
|
|
8
|
+
list: Array<Timeframe>;
|
|
9
|
+
errors: Array<TimeframeError>;
|
|
10
|
+
/**
|
|
11
|
+
* Items that got a new timeframeIdentifier: theirs was missing, or an earlier item already had it
|
|
12
|
+
* (for example an item the editor duplicated). Not an error: write the list back once so the ids
|
|
13
|
+
* are saved. Until then each parse makes different ids.
|
|
14
|
+
*/
|
|
15
|
+
addedKeys: Array<{
|
|
16
|
+
_id: string;
|
|
17
|
+
timeframeIdentifier: string;
|
|
18
|
+
}>;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* The only way editor data enters the module. It never throws and never checks order, overlap or length (that is validate).
|
|
22
|
+
* `undefined` / `null` (no timeframes saved yet) gives an empty list with no errors.
|
|
23
|
+
*/
|
|
24
|
+
export declare function parseList(data: unknown, { newTimeframeId, }?: {
|
|
25
|
+
newTimeframeId?: NewTimeframeId;
|
|
26
|
+
}): ParsedList;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { TimeframeTiming } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* The timeframe showing at `timeMs`: the one with `startMs <= timeMs < endMs`. In a gap, undefined
|
|
4
|
+
* (nothing is shown over the video). At or after `durationMs` (the video ended), the timeframe that
|
|
5
|
+
* ends at the end of the video; if none does, the end is a gap.
|
|
6
|
+
*/
|
|
7
|
+
export declare function activeAt<T extends TimeframeTiming>(list: ReadonlyArray<T>, timeMs: number, durationMs: number): T | undefined;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/** A timeframe that the editor has saved. */
|
|
2
|
+
export type Timeframe = {
|
|
3
|
+
/** The editor's own id. Not in runtime props, so never use it as a React key. */
|
|
4
|
+
_id: string;
|
|
5
|
+
/** Our own stable id. Saved as a text field; use it as the React key. */
|
|
6
|
+
timeframeIdentifier: string;
|
|
7
|
+
/**
|
|
8
|
+
* Owner-only label ("Title" in the panel); may be ''. Called `name` because the editor's array
|
|
9
|
+
* indicator reads `item.name` (and crashes on undefined).
|
|
10
|
+
*/
|
|
11
|
+
name: string;
|
|
12
|
+
/** Integer, inclusive. */
|
|
13
|
+
startMs: number;
|
|
14
|
+
/** Integer, exclusive. */
|
|
15
|
+
endMs: number;
|
|
16
|
+
/** Opaque ref; the editor owns the real container. */
|
|
17
|
+
container?: string;
|
|
18
|
+
/** Stored only; missing = 1. */
|
|
19
|
+
scrollSensitivity?: number;
|
|
20
|
+
};
|
|
21
|
+
/** An item this module asks the editor to create. No _id. */
|
|
22
|
+
export type NewTimeframe = Omit<Timeframe, '_id'>;
|
|
23
|
+
/** Makes a new timeframeIdentifier. Inject one in tests to get fixed ids. */
|
|
24
|
+
export type NewTimeframeId = () => string;
|
|
25
|
+
/** `durationMs` must be a finite, positive whole number. */
|
|
26
|
+
export type Rules = {
|
|
27
|
+
durationMs: number;
|
|
28
|
+
newTimeframeId?: NewTimeframeId;
|
|
29
|
+
};
|
|
30
|
+
/** The only fields `activeAt` needs. */
|
|
31
|
+
export type TimeframeTiming = Pick<NewTimeframe, 'startMs' | 'endMs'>;
|
|
32
|
+
export declare const MIN_LENGTH_MS = 100;
|
|
33
|
+
export declare const MAX_COUNT = 40;
|
|
34
|
+
/**
|
|
35
|
+
* The class on the element that wraps each timeframe's container. The manifest's container
|
|
36
|
+
* `selector` points at it, like Accordion's `.item-content`. The editor needs this selector to find
|
|
37
|
+
* each container. (Saves can still fail with SCHEMA_REFERENCES_NOT_FOUND; that is a server bug.)
|
|
38
|
+
*/
|
|
39
|
+
export declare const TIMEFRAME_CONTENT_CLASS = "timeframe-content";
|
|
40
|
+
/** Length of a new timeframe from createInitial and add, when there is room. */
|
|
41
|
+
export declare const DEFAULT_TIMEFRAME_MS = 5000;
|
|
42
|
+
export type TimeframeErrorCode = 'badTime' | 'tooShort' | 'outOfRange' | 'notSorted' | 'overlap' | 'tooMany' | 'notFound' | 'onBoundary' | 'inGap' | 'insideTimeframe' | 'noRoom' | 'badSensitivity' | 'badItem' | 'badKey' | 'duplicateKey' | 'duplicateId';
|
|
43
|
+
export type TimeframeError = {
|
|
44
|
+
code: TimeframeErrorCode;
|
|
45
|
+
/**
|
|
46
|
+
* Position in the list, or -1 for whole-list problems. For a parseList `badItem` it is the
|
|
47
|
+
* position in the raw editor data: that item is not in `parsed.list`, which is also sorted.
|
|
48
|
+
*/
|
|
49
|
+
index: number;
|
|
50
|
+
_id?: string;
|
|
51
|
+
};
|
|
52
|
+
export type Result = {
|
|
53
|
+
ok: true;
|
|
54
|
+
list: Array<Timeframe | NewTimeframe>;
|
|
55
|
+
index: number;
|
|
56
|
+
} | {
|
|
57
|
+
ok: false;
|
|
58
|
+
errors: Array<TimeframeError>;
|
|
59
|
+
};
|
|
60
|
+
export declare const timeframeError: (code: TimeframeErrorCode, index: number, _id?: unknown) => TimeframeError;
|
|
61
|
+
/** A video length the rules accept: a positive whole number of ms. */
|
|
62
|
+
export declare const isDuration: (durationMs: number | undefined) => durationMs is number;
|
|
63
|
+
export declare function assertDuration(durationMs: number): void;
|
|
64
|
+
export declare function assertList(list: unknown): void;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { TimeframeTiming } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* The index of the timeframe showing in `video` now. It re-renders only when the index changes.
|
|
4
|
+
* `durationMs` comes from the data. Undefined or invalid gives undefined.
|
|
5
|
+
* Before a video is attached (and on the server), it is the timeframe at time 0.
|
|
6
|
+
* Pass a stable `timeframes` array (memoized): a new array restarts the video listeners.
|
|
7
|
+
*/
|
|
8
|
+
export declare function useActiveTimeframeIndex<T extends TimeframeTiming>(timeframes: ReadonlyArray<T>, video: HTMLVideoElement | null, durationMs: number | undefined): number | undefined;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { TimeframeError, NewTimeframe, Rules } from './types';
|
|
2
|
+
type Item = NewTimeframe & {
|
|
3
|
+
_id?: string;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* Like validate, but without checking durationMs. For internal use. By default one error per item
|
|
7
|
+
* (the first problem); `all` gives every problem, which the edits need to compare before and after.
|
|
8
|
+
*/
|
|
9
|
+
export declare function collectErrors(list: ReadonlyArray<Item>, durationMs: number, { all }?: {
|
|
10
|
+
all?: boolean;
|
|
11
|
+
}): Array<TimeframeError>;
|
|
12
|
+
/**
|
|
13
|
+
* Checks a list: sorted by startMs, no overlap (touching is fine), every timeframe at least
|
|
14
|
+
* MIN_LENGTH_MS and inside `[0, durationMs]`. Gaps and an empty list are valid.
|
|
15
|
+
*/
|
|
16
|
+
export declare function validate(list: ReadonlyArray<Item>, rules: Rules): Array<TimeframeError>;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calls onTimeMs with toMs(video.currentTime) and video.ended whenever either may have changed.
|
|
3
|
+
* `ended` is true when the video is scrubbed to the end, and currentTime may stop a bit before the
|
|
4
|
+
* real end, so a caller that needs "the end" should check `ended`, not the time.
|
|
5
|
+
* Returns stop(), which is safe to call twice.
|
|
6
|
+
*/
|
|
7
|
+
export declare function watchVideoTime(video: HTMLVideoElement, onTimeMs: (timeMs: number, ended: boolean) => void): () => void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/editor-react-components",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2749.0",
|
|
4
4
|
"description": "React components for the Wix Editor",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -116,7 +116,7 @@
|
|
|
116
116
|
"@wix/ambassador-devcenter-v1-component-type-data": "^1.0.576",
|
|
117
117
|
"@wix/astro": "^2.73.0",
|
|
118
118
|
"@wix/business-tools": "^1.0.233",
|
|
119
|
-
"@wix/cli": "^1.1.
|
|
119
|
+
"@wix/cli": "^1.1.262",
|
|
120
120
|
"@wix/cli-app": "^1.1.260",
|
|
121
121
|
"@wix/component-protocol": "^1.253.0",
|
|
122
122
|
"@wix/components-infra": "^1.0.0",
|
|
@@ -222,5 +222,5 @@
|
|
|
222
222
|
"registry": "https://registry.npmjs.org/",
|
|
223
223
|
"access": "public"
|
|
224
224
|
},
|
|
225
|
-
"falconPackageHash": "
|
|
225
|
+
"falconPackageHash": "4308638f3d5b885f504d39750fffccea1e3377db04ca7104e417300c"
|
|
226
226
|
}
|