@design-edito/tools 0.5.2 → 0.5.4
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/agnostic/html/deep-select/index.js +5 -3
- package/agnostic/html/hyper-json/smart-tags/coalesced/index.d.ts +9 -9
- package/agnostic/html/hyper-json/smart-tags/coalesced/index.js +9 -9
- package/agnostic/html/hyper-json/smart-tags/isolated/index.d.ts +3 -3
- package/agnostic/html/hyper-json/smart-tags/isolated/index.js +3 -3
- package/agnostic/html/index.d.ts +1 -1
- package/agnostic/html/index.js +1 -1
- package/agnostic/index.d.ts +2 -2
- package/agnostic/index.js +2 -2
- package/agnostic/misc/index.d.ts +3 -3
- package/agnostic/misc/index.js +3 -3
- package/agnostic/misc/logs/index.d.ts +1 -1
- package/agnostic/misc/logs/index.js +1 -1
- package/agnostic/numbers/index.d.ts +1 -1
- package/agnostic/numbers/index.js +1 -1
- package/agnostic/optim/index.d.ts +1 -1
- package/agnostic/optim/index.js +1 -1
- package/agnostic/strings/index.d.ts +2 -2
- package/agnostic/strings/index.js +2 -2
- package/agnostic/time/dates/format-date/index.d.ts +4 -2
- package/agnostic/time/dates/format-date/index.js +43 -94
- package/agnostic/time/dates/format-date/index.test.js +154 -0
- package/agnostic/time/dates/format-date/parts.d.ts +28 -0
- package/agnostic/time/dates/format-date/parts.js +136 -0
- package/agnostic/time/dates/format-date/types.d.ts +84 -0
- package/agnostic/time/dates/format-date/types.js +1 -0
- package/agnostic/time/duration/format-duration/index.d.ts +42 -0
- package/agnostic/time/duration/format-duration/index.js +94 -0
- package/agnostic/time/duration/format-duration/index.test.d.ts +1 -0
- package/agnostic/time/duration/format-duration/index.test.js +148 -0
- package/agnostic/time/duration/format-duration/parts.d.ts +32 -0
- package/agnostic/time/duration/format-duration/parts.js +107 -0
- package/agnostic/time/duration/format-duration/types.d.ts +93 -0
- package/agnostic/time/duration/format-duration/types.js +1 -0
- package/agnostic/time/duration/index.d.ts +6 -1
- package/agnostic/time/duration/index.js +2 -2
- package/agnostic/time/duration/index.test.d.ts +1 -0
- package/agnostic/time/duration/index.test.js +168 -0
- package/agnostic/time/index.d.ts +1 -1
- package/agnostic/time/index.js +1 -1
- package/components/BeforeAfter/index.controlled.d.ts +25 -25
- package/components/BeforeAfter/index.controlled.js +47 -53
- package/components/BeforeAfter/index.d.ts +20 -23
- package/components/BeforeAfter/index.js +48 -40
- package/components/Button/index.js +1 -1
- package/components/Clippable/index.d.ts +17 -26
- package/components/Clippable/index.js +21 -23
- package/components/Disclaimer/index.d.ts +32 -24
- package/components/Disclaimer/index.js +29 -24
- package/components/Drawer/index.d.ts +45 -25
- package/components/Drawer/index.js +61 -52
- package/components/EventListener/index.d.ts +4 -5
- package/components/Gallery/index.d.ts +14 -16
- package/components/Gallery/index.js +25 -30
- package/components/Iframe/index.js +2 -2
- package/components/Image/index.d.ts +5 -15
- package/components/Image/index.js +9 -34
- package/components/Input/index.d.ts +23 -19
- package/components/Input/index.js +30 -20
- package/components/JsonEditor/index.d.ts +177 -9
- package/components/JsonEditor/index.js +133 -77
- package/components/JsonEditor/types.d.ts +11 -0
- package/components/JsonEditor/types.js +1 -0
- package/components/JsonEditor/utils.d.ts +8 -0
- package/components/JsonEditor/utils.js +23 -0
- package/components/ListLoader/index.controlled.d.ts +5 -5
- package/components/ListLoader/index.controlled.js +4 -4
- package/components/ListLoader/index.d.ts +11 -11
- package/components/ListLoader/index.js +12 -12
- package/components/Overlayer/index.d.ts +4 -4
- package/components/Overlayer/index.js +6 -6
- package/components/Paginator/index.d.ts +7 -12
- package/components/Paginator/index.js +7 -11
- package/components/ResizeObserver/index.d.ts +14 -3
- package/components/ResizeObserver/index.js +49 -24
- package/components/Scrllgngn/index.d.ts +17 -13
- package/components/Scrllgngn/index.js +25 -84
- package/components/Scrllgngn/utils.d.ts +52 -0
- package/components/Scrllgngn/utils.js +102 -0
- package/components/ScrollListener/index.d.ts +43 -28
- package/components/ScrollListener/index.js +59 -79
- package/components/ScrollListener/utils.d.ts +37 -16
- package/components/ScrollListener/utils.js +141 -28
- package/components/Select/index.d.ts +24 -20
- package/components/Select/index.js +30 -20
- package/components/Sequencer/index.controlled.d.ts +16 -26
- package/components/Sequencer/index.controlled.js +15 -12
- package/components/Sequencer/index.d.ts +25 -30
- package/components/Sequencer/index.js +20 -34
- package/components/Subtitles/index.d.ts +29 -5
- package/components/Subtitles/index.js +90 -12
- package/components/Textarea/index.d.ts +26 -20
- package/components/Textarea/index.js +40 -21
- package/components/Theatre/index.d.ts +35 -39
- package/components/Theatre/index.js +46 -58
- package/components/UIModule/index.d.ts +25 -29
- package/components/UIModule/index.js +81 -110
- package/components/Video/index.controlled.d.ts +51 -51
- package/components/Video/index.controlled.js +75 -72
- package/components/Video/index.d.ts +12 -14
- package/components/Video/index.js +41 -86
- package/components/Video/utils.d.ts +35 -3
- package/components/Video/utils.js +37 -14
- package/components/index.d.ts +6 -6
- package/components/index.js +6 -6
- package/components/utils/index.d.ts +22 -0
- package/components/utils/index.js +31 -0
- package/index.d.ts +1 -1
- package/index.js +1 -1
- package/node/@aws-s3/storage/directory/index.d.ts +2 -2
- package/node/@aws-s3/storage/directory/index.js +2 -2
- package/node/@aws-s3/storage/file/index.d.ts +1 -1
- package/node/@aws-s3/storage/file/index.js +1 -1
- package/node/@aws-s3/storage/index.d.ts +1 -1
- package/node/@aws-s3/storage/index.js +1 -1
- package/node/@google-cloud/storage/directory/index.d.ts +2 -2
- package/node/@google-cloud/storage/directory/index.js +2 -2
- package/node/@google-cloud/storage/file/index.d.ts +2 -2
- package/node/@google-cloud/storage/file/index.js +2 -2
- package/node/@google-cloud/storage/index.d.ts +1 -1
- package/node/@google-cloud/storage/index.js +1 -1
- package/node/cloud-storage/operations/index.d.ts +2 -2
- package/node/cloud-storage/operations/index.js +2 -2
- package/node/ftps/file/index.d.ts +2 -2
- package/node/ftps/file/index.js +2 -2
- package/node/images/index.d.ts +1 -1
- package/node/images/index.js +1 -1
- package/node/images/transform/operations/index.d.ts +2 -2
- package/node/images/transform/operations/index.js +2 -2
- package/node/index.d.ts +1 -1
- package/node/index.js +1 -1
- package/node/process/index.d.ts +1 -1
- package/node/process/index.js +1 -1
- package/node/sftp/file/index.d.ts +2 -2
- package/node/sftp/file/index.js +2 -2
- package/node/sftp/index.d.ts +1 -1
- package/node/sftp/index.js +1 -1
- package/package.json +20 -5
- package/TODO.md +0 -269
- package/components/BeforeAfter/utils.d.ts +0 -4
- package/components/BeforeAfter/utils.js +0 -9
- package/components/Input/index.controlled.d.ts +0 -42
- package/components/Input/index.controlled.js +0 -54
- package/components/Select/index.controlled.d.ts +0 -43
- package/components/Select/index.controlled.js +0 -54
- package/components/Subtitles/types.d.ts +0 -24
- package/components/Subtitles/utils.d.ts +0 -32
- package/components/Subtitles/utils.js +0 -107
- package/components/Textarea/index.controlled.d.ts +0 -50
- package/components/Textarea/index.controlled.js +0 -75
- /package/{components/Subtitles/types.js → agnostic/time/dates/format-date/index.test.d.ts} +0 -0
- /package/components/ResizeObserver/{style.module.css → styles.module.css} +0 -0
package/TODO.md
DELETED
|
@@ -1,269 +0,0 @@
|
|
|
1
|
-
# To do
|
|
2
|
-
|
|
3
|
-
# -
|
|
4
|
-
|
|
5
|
-
Après le dev :
|
|
6
|
-
- envoyer le code à GPT + Claude, leur demander:
|
|
7
|
-
1/ s'ils comprennent le fichier, on veut juste s'assurer qu'on est raccord avec lui à ce stade
|
|
8
|
-
2/ en gardant en tête de garder le périmètre fonctionnel intact, sans chercher à faire plus ce qu'il y a actuellement, de relever les nommages ou formes de code qui pourraient être améliorées pour que le fichier soit prêt à intégrer une librairie de composants solide, durable dans le temps et facile à maintenir. Préciser qu'il faut respecter les règles de standardjs pour le lint
|
|
9
|
-
- essayer de build, régler les erreurs du linter
|
|
10
|
-
- après ça, fournir à GPT/Claude un exemple de fichier test d'un autre composant, Drawer par ex, + le code actuel de Subtitles, et lui demander de garder le style/approche fourni, et générer les tests pertinents pour le composant Subtitles (utiliser srtFileContents et pas src, ça va être une galère). Lui rappeler que les tests sont évalués par nodejs, donc pas trop se reposer sur des choses qui se passent dans un browser. Pas trop besoin de checker le contenu du fichier de test, moi je prends ce qu'il me donne, je lance le test et espère que ça passe tout, si ça passe pas tu peux lui donner le contenu de l'erreur et voir si il arrive à régler le truc tout seul, si ça veut vraiment pas, commente l'intégralité du test qui bloque, tant pis.
|
|
11
|
-
- ensuite une fois que c'est bon, fournir à GPT/Claude un exemple de JSDOC issu d'un autre composant, Gallery par ex, + le code actuel de Subtitles, et lui demander de générer le JSDOC pour tous les exported members de Subtitles (Props et Subtitles à priori). Juste le JSDOC, pas répéter le code, parfois en générant tout il glisse des erreurs en répétant le code.
|
|
12
|
-
- re build, lint et corrections éventuelles des erreurs du linter
|
|
13
|
-
- pull add commit push 🎉
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
# Composants
|
|
17
|
-
|
|
18
|
-
## Composant Vidéo
|
|
19
|
-
|
|
20
|
-
/components/Video
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
### D'abord, on va reprendre new-app/src/components/VideoPlayer/MutedVideo.tsx
|
|
24
|
-
Ce composant permet un workaround d'une petite bizzarerie de react avec l'attribut muted.
|
|
25
|
-
Ça va être notre composant vidéo de base, pour ne pas manipuler directement l'élément html vidéo.
|
|
26
|
-
|
|
27
|
-
### Ensuite, un composant tout simple :
|
|
28
|
-
|
|
29
|
-
// "on" evt listeners
|
|
30
|
-
// "state/props"
|
|
31
|
-
// "int/obs triggers"
|
|
32
|
-
// disclaimer
|
|
33
|
-
// subs
|
|
34
|
-
|
|
35
|
-
- une vidéo :
|
|
36
|
-
```tsx
|
|
37
|
-
type SourceData = {
|
|
38
|
-
src?: string
|
|
39
|
-
type?: string
|
|
40
|
-
}
|
|
41
|
-
type TrackData = {
|
|
42
|
-
src?: string
|
|
43
|
-
kind?: 'subtitles' | 'captions' | 'descriptions' | 'chapters' | 'metadata'
|
|
44
|
-
srclang?: string
|
|
45
|
-
label?: string
|
|
46
|
-
default?: boolean
|
|
47
|
-
}
|
|
48
|
-
type Props = {
|
|
49
|
-
sources?: string | string[] | SourceData[] // liste des éléments <source> dans la vidéo (ignore si pas src dans SourceData)
|
|
50
|
-
tracks?: string | string[] | TrackData[] // liste des éléments <tracks> dans la vidéo (ignore si pas src dans TrackData)
|
|
51
|
-
children?: JSX.Element // react children habituel, vient se coller sous les <source> et <tracks>
|
|
52
|
-
} & VideoHTMLAttributes<HTMLVideoElement>
|
|
53
|
-
|
|
54
|
-
const {
|
|
55
|
-
sources,
|
|
56
|
-
tracks,
|
|
57
|
-
children,
|
|
58
|
-
...intrinsicVideoAttributes
|
|
59
|
-
} = props
|
|
60
|
-
```
|
|
61
|
-
- un bouton play
|
|
62
|
-
- sur lm-video :
|
|
63
|
-
- data-play-on
|
|
64
|
-
- lm-video--play-on
|
|
65
|
-
- un bouton pause
|
|
66
|
-
- sur lm-video :
|
|
67
|
-
- data-play-off
|
|
68
|
-
- lm-video--play-off
|
|
69
|
-
- un span "temps écoulé"
|
|
70
|
-
- sur lm-video :
|
|
71
|
-
- data-elapsed-time-percent (0-1)
|
|
72
|
-
- data-elapsed-time-ms
|
|
73
|
-
- data-elapsed-time-readable ((hh:)mm:ss)
|
|
74
|
-
- un span "temps total"
|
|
75
|
-
- sur lm-video :
|
|
76
|
-
- data-total-time-ms
|
|
77
|
-
- data-total-time-readable
|
|
78
|
-
- une div cliquable en guise de timeline (pas de curseur)
|
|
79
|
-
- un bouton sound on
|
|
80
|
-
- sur lm-video:
|
|
81
|
-
- data-sound-on
|
|
82
|
-
- lm-video--sound-on
|
|
83
|
-
- un bouton sound off
|
|
84
|
-
- sur lm-video:
|
|
85
|
-
- data-sound-off
|
|
86
|
-
- lm-video--sound-off
|
|
87
|
-
- un input range (0 - 100, step=1) pour piloter le son
|
|
88
|
-
- sur lm-video:
|
|
89
|
-
- data-sound-volume-percent (0-1) (ne se met pas à 0 si sound off, c'est deux données séparées)
|
|
90
|
-
- data-sound-volume-readable (0-100)
|
|
91
|
-
- un span "volume (0-100)"
|
|
92
|
-
- un bouton full screen
|
|
93
|
-
- sur lm-video:
|
|
94
|
-
- data-fullscreen-on / data-full-screen-off
|
|
95
|
-
- lm-video--fullscreen-on / lm-video--fullscreen-off
|
|
96
|
-
- un bouton download
|
|
97
|
-
- un input range playback-speed (0.25-4 step=0.25)
|
|
98
|
-
- sur lm-video:
|
|
99
|
-
- data-playback-speed (.25-4)
|
|
100
|
-
- un span "playback speed (.25-4)"
|
|
101
|
-
|
|
102
|
-
### Suite [WIP]
|
|
103
|
-
|
|
104
|
-
[ ] Click sur timeline ne semble pas marcher ?
|
|
105
|
-
[ ]
|
|
106
|
-
|
|
107
|
-
- Gérer la partie "controlled behavior" tout d'un coup
|
|
108
|
-
[ ] Idée : quand la vidéo est en mode controlled,
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
## Composant Subtitles
|
|
116
|
-
|
|
117
|
-
lm-tools/src/components/Subtitles/index.tsx
|
|
118
|
-
|
|
119
|
-
```tsx
|
|
120
|
-
<Subtitles
|
|
121
|
-
src='srt.file.url'
|
|
122
|
-
srtFileContent='Contenu srt brut, si présent la prop src est ignorée.'
|
|
123
|
-
subsGroups={[3, 4, 5]}
|
|
124
|
-
timecodeMs={10000}>
|
|
125
|
-
</Subtitles>
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
```html
|
|
129
|
-
<div class="lm-subtitles">
|
|
130
|
-
<!-- Groupe passé (donc que sub prev dedans) -->
|
|
131
|
-
<div
|
|
132
|
-
class="lm-subtitles__group lm-subtitles__group--prev"
|
|
133
|
-
data-start-sub-pos="0"
|
|
134
|
-
data-end-sub-pos="1">
|
|
135
|
-
<span class="lm-subtitles__sub lm-subtitles__sub--prev" data-sub-pos="0">
|
|
136
|
-
Some sub
|
|
137
|
-
</span>
|
|
138
|
-
</div>
|
|
139
|
-
<!-- Groupe courant (mix de sub prev, curr et next) -->
|
|
140
|
-
<div
|
|
141
|
-
class="lm-subtitles__group lm-subtitles__group--curr"
|
|
142
|
-
data-start-timecode="00:02:16,612"
|
|
143
|
-
data-end-timecode="00:02:16,612"
|
|
144
|
-
data-start-time-ms="34754382"
|
|
145
|
-
data-end-time-ms="34754382"
|
|
146
|
-
data-start-sub-pos="0"
|
|
147
|
-
data-end-sub-pos="1">
|
|
148
|
-
<span
|
|
149
|
-
class="lm-subtitles__sub lm-subtitles__sub--curr"
|
|
150
|
-
data-start-timecode="00:02:16,612"
|
|
151
|
-
data-end-timecode="00:02:16,612"
|
|
152
|
-
data-start-time-ms="34754382"
|
|
153
|
-
data-end-time-ms="34754382">
|
|
154
|
-
Some sub
|
|
155
|
-
</span>
|
|
156
|
-
</div>
|
|
157
|
-
<!-- Groupe à venir -->
|
|
158
|
-
<div
|
|
159
|
-
class="lm-subtitles__group lm-subtitles__group--prev"
|
|
160
|
-
data-start-timecode="00:02:16,612"
|
|
161
|
-
data-end-timecode="00:02:16,612"
|
|
162
|
-
data-start-time-ms="34754382"
|
|
163
|
-
data-end-time-ms="34754382"
|
|
164
|
-
data-start-sub-pos="0"
|
|
165
|
-
data-end-sub-pos="1">
|
|
166
|
-
<span
|
|
167
|
-
class="lm-subtitles__sub lm-subtitles__sub--prev"
|
|
168
|
-
data-start-timecode="00:02:16,612"
|
|
169
|
-
data-end-timecode="00:02:16,612"
|
|
170
|
-
data-start-time-ms="34754382"
|
|
171
|
-
data-end-time-ms="34754382">
|
|
172
|
-
Some sub
|
|
173
|
-
</span>
|
|
174
|
-
</div>
|
|
175
|
-
</div>
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
# CLI Utils
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
## Get diff from commit hash
|
|
185
|
-
|
|
186
|
-
```ts
|
|
187
|
-
export type GetDiffOptions = {
|
|
188
|
-
cwd?: string
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// Pas certain de Array<string> mais c'est peut-être suffisant,
|
|
192
|
-
// l'idée c'est d'avoir une liste descriptive des changements successifs sur un fichier (genre le contenu brut de git diff)
|
|
193
|
-
export type Diff = Record<string, Array<string>>
|
|
194
|
-
|
|
195
|
-
// Ou pas async si pas nécessaire
|
|
196
|
-
export async function getDiffFrom (
|
|
197
|
-
commitHash: string,
|
|
198
|
-
options: GetDiffOptions = {}
|
|
199
|
-
): Promise<Diff> {
|
|
200
|
-
const { cwd } = options
|
|
201
|
-
return {}
|
|
202
|
-
}
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
## Generate commit message from diff
|
|
206
|
-
|
|
207
|
-
```ts
|
|
208
|
-
export type GenerateDiffDescriptionOptions = {
|
|
209
|
-
customPromptOrSomething?: string // juste une idée comme ça, sais pas si c'est pertinent
|
|
210
|
-
// Ptet c'est là qu'il faut dire "je veux plutôt un changelog, ou plutôt un message de commit"
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
export async function generateDiffDescription (
|
|
214
|
-
diff: Diff,
|
|
215
|
-
options: GenerateDiffDescriptionOptions = {}): Promise<string> {
|
|
216
|
-
return ''
|
|
217
|
-
}
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
# Tests & JSDOC
|
|
224
|
-
|
|
225
|
-
- [ ] Tests manquants (garder la forme describe('funcName') { it('does something') {} })
|
|
226
|
-
- [ ] agnostic/html/hyper-json -> nécessaire mais trop compliqué/long
|
|
227
|
-
- [ ] agnostic/html/placeholders -> pas nécessaire
|
|
228
|
-
- [ ] agnostic/misc/logs/make-text-block -> Manque JSDOC aussi
|
|
229
|
-
- [ ] agnostic/strings/char-codes
|
|
230
|
-
- [ ] agnostic/strings/matches
|
|
231
|
-
- [ ] agnostic/strings/parse-table
|
|
232
|
-
- [ ] agnostic/strings/to-alphanum
|
|
233
|
-
- [ ] agnostic/strings/trim
|
|
234
|
-
- [ ] agnostic/time/dates/format-date
|
|
235
|
-
- [ ] agnostic/time/duration
|
|
236
|
-
- [ ] agnostic/time/timeout
|
|
237
|
-
- [ ] agnostic/time/transitions
|
|
238
|
-
- [ ] agnostic/time/wait
|
|
239
|
-
- [ ] node/@aws-s3 - oui mais comment (valable aussi pour gcs, ftps & sftp) ?
|
|
240
|
-
- [ ] node/@design-edito - vide
|
|
241
|
-
- [ ] node/@express/@multer
|
|
242
|
-
- [ ] node/@google-cloud
|
|
243
|
-
- [ ] node/cloud-storage
|
|
244
|
-
- [ ] node/encryption
|
|
245
|
-
- [ ] node/files
|
|
246
|
-
- [ ] node/ftps
|
|
247
|
-
- [ ] node/images
|
|
248
|
-
- [ ] node/process
|
|
249
|
-
- [ ] node/sftp
|
|
250
|
-
|
|
251
|
-
- Pas utile
|
|
252
|
-
- [ ] agnostic/css/bem -> DEPRECATED
|
|
253
|
-
- [ ] agnostic/css/styles-set -> DEPRECATED
|
|
254
|
-
- [ ] agnostic/errors/register -> pas nécessaire
|
|
255
|
-
- [ ] agnostic/html/sanitization/html -> DEPRECATED
|
|
256
|
-
- [ ] agnostic/misc/assert -> DEPRECATED
|
|
257
|
-
- [ ] agnostic/misc/logs/logger -> presque DEPRECATED
|
|
258
|
-
- [ ] agnostic/misc/logs/styles -> pas nécessaire tout de suite
|
|
259
|
-
- [ ] agnostic/strings/normalize-indent -> pas nécessaire tout de suite, fonction à repenser
|
|
260
|
-
- [ ] agnostic/strings/replace-all -> DEPRECATED
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
# Misc
|
|
265
|
-
|
|
266
|
-
- [ ] Repenser agnostic/optim/throttle-debounce ?
|
|
267
|
-
- [ ] Repenser agnostic/strings/normalize-indent ?
|
|
268
|
-
- [ ] Get rid of namespaces in hyper-json ?
|
|
269
|
-
- [ ] agnostic/misc/logs/styles, se repencher dessus, viser à substituer totalement chalk (styles génériques, bold, red, bgBlue, etc...) + continuer à exporter des "styles nommés" comme actuellement
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export function getRelativePointerCoordinates(event, element) {
|
|
2
|
-
if (element === null) {
|
|
3
|
-
return { x: 0, y: 0 };
|
|
4
|
-
}
|
|
5
|
-
const rect = element.getBoundingClientRect();
|
|
6
|
-
const x = event.clientX - rect.left;
|
|
7
|
-
const y = event.clientY - rect.top;
|
|
8
|
-
return { x, y };
|
|
9
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { type FunctionComponent, type InputHTMLAttributes, type ReactNode } from 'react';
|
|
2
|
-
import type { WithClassName } from '../utils/types.js';
|
|
3
|
-
/**
|
|
4
|
-
* Props for the {@link ControlledInput} component.
|
|
5
|
-
*
|
|
6
|
-
* Extends all native {@link InputHTMLAttributes} and {@link WithClassName}
|
|
7
|
-
* with optional label and error content.
|
|
8
|
-
*
|
|
9
|
-
* @property label - Content rendered as an associated `<label>`. When omitted, no label is rendered.
|
|
10
|
-
* @property error - Content rendered as an error message below the input. When omitted, no error is rendered.
|
|
11
|
-
* @property className - Additional class name(s) applied to the root element.
|
|
12
|
-
*/
|
|
13
|
-
export type Props = InputHTMLAttributes<HTMLInputElement> & WithClassName<{
|
|
14
|
-
label?: ReactNode;
|
|
15
|
-
error?: ReactNode;
|
|
16
|
-
}>;
|
|
17
|
-
/**
|
|
18
|
-
* Controlled input field component.
|
|
19
|
-
*
|
|
20
|
-
* Renders a native `<input>` element with optional label and error feedback.
|
|
21
|
-
* The input value is entirely driven by the provided `value` prop and all
|
|
22
|
-
* native input attributes are forwarded to the underlying element.
|
|
23
|
-
*
|
|
24
|
-
* A stable auto-generated `id` is created on mount and used to associate the
|
|
25
|
-
* rendered label through the `htmlFor` attribute.
|
|
26
|
-
*
|
|
27
|
-
* ### CSS elements
|
|
28
|
-
* - `label`
|
|
29
|
-
* - `error`
|
|
30
|
-
*
|
|
31
|
-
* @param props - Component properties.
|
|
32
|
-
* @see {@link Props}
|
|
33
|
-
*
|
|
34
|
-
* @returns A labelled controlled input with optional error feedback.
|
|
35
|
-
*
|
|
36
|
-
* @remarks
|
|
37
|
-
* - The component does not manage its own value state.
|
|
38
|
-
* - Consumers are responsible for updating `value` in response to `onChange`.
|
|
39
|
-
* - Additional `className` values are merged with the component public class name
|
|
40
|
-
* and applied to the underlying `<input>` element.
|
|
41
|
-
*/
|
|
42
|
-
export declare const ControlledInput: FunctionComponent<Props>;
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useState } from 'react';
|
|
3
|
-
import { clss } from '../../agnostic/css/clss/index.js';
|
|
4
|
-
import { isNotFalsy } from '../../agnostic/booleans/is-falsy/index.js';
|
|
5
|
-
import { randomHash } from '../../agnostic/random/uuid/index.js';
|
|
6
|
-
import { input as publicClassName } from '../public-classnames.js';
|
|
7
|
-
import { mergeClassNames } from '../utils/index.js';
|
|
8
|
-
import cssModule from './styles.module.css';
|
|
9
|
-
/**
|
|
10
|
-
* Controlled input field component.
|
|
11
|
-
*
|
|
12
|
-
* Renders a native `<input>` element with optional label and error feedback.
|
|
13
|
-
* The input value is entirely driven by the provided `value` prop and all
|
|
14
|
-
* native input attributes are forwarded to the underlying element.
|
|
15
|
-
*
|
|
16
|
-
* A stable auto-generated `id` is created on mount and used to associate the
|
|
17
|
-
* rendered label through the `htmlFor` attribute.
|
|
18
|
-
*
|
|
19
|
-
* ### CSS elements
|
|
20
|
-
* - `label`
|
|
21
|
-
* - `error`
|
|
22
|
-
*
|
|
23
|
-
* @param props - Component properties.
|
|
24
|
-
* @see {@link Props}
|
|
25
|
-
*
|
|
26
|
-
* @returns A labelled controlled input with optional error feedback.
|
|
27
|
-
*
|
|
28
|
-
* @remarks
|
|
29
|
-
* - The component does not manage its own value state.
|
|
30
|
-
* - Consumers are responsible for updating `value` in response to `onChange`.
|
|
31
|
-
* - Additional `className` values are merged with the component public class name
|
|
32
|
-
* and applied to the underlying `<input>` element.
|
|
33
|
-
*/
|
|
34
|
-
export const ControlledInput = ({ label, error, value, className, ...rest }) => {
|
|
35
|
-
const [id] = useState(`_${randomHash(12)}`);
|
|
36
|
-
const c = clss(publicClassName, { cssModule });
|
|
37
|
-
const rootClss = mergeClassNames(c(null), className);
|
|
38
|
-
return _jsxs(_Fragment, { children: [isNotFalsy(label) && _jsx("label", { className: c('label'), htmlFor: id, children: label }), _jsx("input", { ...rest, id: id, className: rootClss, value: value ?? '', onChange: e => {
|
|
39
|
-
const { target } = e;
|
|
40
|
-
rest.onChange?.(e);
|
|
41
|
-
if (value === undefined)
|
|
42
|
-
return;
|
|
43
|
-
if (typeof value === 'number') {
|
|
44
|
-
target.value = `${value}`;
|
|
45
|
-
}
|
|
46
|
-
else if (typeof value === 'string') {
|
|
47
|
-
target.value = value;
|
|
48
|
-
}
|
|
49
|
-
else {
|
|
50
|
-
// value is readonly string[]
|
|
51
|
-
// not supported for <input>; ignore or normalize if needed
|
|
52
|
-
}
|
|
53
|
-
} }), isNotFalsy(error) && _jsx("span", { className: c('error'), children: error })] });
|
|
54
|
-
};
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { type FunctionComponent, type SelectHTMLAttributes, type ReactNode, type PropsWithChildren } from 'react';
|
|
2
|
-
import type { WithClassName } from '../utils/types.js';
|
|
3
|
-
/**
|
|
4
|
-
* Props for the {@link ControlledSelect} component.
|
|
5
|
-
*
|
|
6
|
-
* Extends all native {@link SelectHTMLAttributes} and {@link WithClassName}
|
|
7
|
-
* with optional label, error content, and option children.
|
|
8
|
-
*
|
|
9
|
-
* @property label - Content rendered as an associated `<label>`. When omitted, no label is rendered.
|
|
10
|
-
* @property error - Content rendered as an error message below the select. When omitted, no error is rendered.
|
|
11
|
-
* @property className - Additional class name(s) applied to the select element.
|
|
12
|
-
* @property children - `<option>` or `<optgroup>` elements rendered inside the select.
|
|
13
|
-
*/
|
|
14
|
-
export type Props = SelectHTMLAttributes<HTMLSelectElement> & PropsWithChildren<WithClassName<{
|
|
15
|
-
label?: ReactNode;
|
|
16
|
-
error?: ReactNode;
|
|
17
|
-
}>>;
|
|
18
|
-
/**
|
|
19
|
-
* Controlled select field component.
|
|
20
|
-
*
|
|
21
|
-
* Renders a native `<select>` element with optional label and error feedback.
|
|
22
|
-
* The selected value is entirely driven by the provided `value` prop and all
|
|
23
|
-
* native select attributes are forwarded to the underlying element.
|
|
24
|
-
*
|
|
25
|
-
* A stable auto-generated `id` is created on mount and used to associate the
|
|
26
|
-
* rendered label through the `htmlFor` attribute.
|
|
27
|
-
*
|
|
28
|
-
* ### CSS elements
|
|
29
|
-
* - `label`
|
|
30
|
-
* - `error`
|
|
31
|
-
*
|
|
32
|
-
* @param props - Component properties.
|
|
33
|
-
* @see {@link Props}
|
|
34
|
-
*
|
|
35
|
-
* @returns A labelled controlled select with optional error feedback.
|
|
36
|
-
*
|
|
37
|
-
* @remarks
|
|
38
|
-
* - The component does not manage its own selection state.
|
|
39
|
-
* - Consumers are responsible for updating `value` in response to `onChange`.
|
|
40
|
-
* - Additional `className` values are merged with the component public class name
|
|
41
|
-
* and applied to the underlying `<select>` element.
|
|
42
|
-
*/
|
|
43
|
-
export declare const ControlledSelect: FunctionComponent<Props>;
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useState } from 'react';
|
|
3
|
-
import { clss } from '../../agnostic/css/clss/index.js';
|
|
4
|
-
import { isNotFalsy } from '../../agnostic/booleans/is-falsy/index.js';
|
|
5
|
-
import { randomHash } from '../../agnostic/random/uuid/index.js';
|
|
6
|
-
import { select as publicClassName } from '../public-classnames.js';
|
|
7
|
-
import { mergeClassNames } from '../utils/index.js';
|
|
8
|
-
import cssModule from './styles.module.css';
|
|
9
|
-
/**
|
|
10
|
-
* Controlled select field component.
|
|
11
|
-
*
|
|
12
|
-
* Renders a native `<select>` element with optional label and error feedback.
|
|
13
|
-
* The selected value is entirely driven by the provided `value` prop and all
|
|
14
|
-
* native select attributes are forwarded to the underlying element.
|
|
15
|
-
*
|
|
16
|
-
* A stable auto-generated `id` is created on mount and used to associate the
|
|
17
|
-
* rendered label through the `htmlFor` attribute.
|
|
18
|
-
*
|
|
19
|
-
* ### CSS elements
|
|
20
|
-
* - `label`
|
|
21
|
-
* - `error`
|
|
22
|
-
*
|
|
23
|
-
* @param props - Component properties.
|
|
24
|
-
* @see {@link Props}
|
|
25
|
-
*
|
|
26
|
-
* @returns A labelled controlled select with optional error feedback.
|
|
27
|
-
*
|
|
28
|
-
* @remarks
|
|
29
|
-
* - The component does not manage its own selection state.
|
|
30
|
-
* - Consumers are responsible for updating `value` in response to `onChange`.
|
|
31
|
-
* - Additional `className` values are merged with the component public class name
|
|
32
|
-
* and applied to the underlying `<select>` element.
|
|
33
|
-
*/
|
|
34
|
-
export const ControlledSelect = ({ label, error, value, className, children, ...rest }) => {
|
|
35
|
-
const [id] = useState(`_${randomHash(12)}`);
|
|
36
|
-
const c = clss(publicClassName, { cssModule });
|
|
37
|
-
const rootClss = mergeClassNames(c(null), className);
|
|
38
|
-
return _jsxs(_Fragment, { children: [isNotFalsy(label) && _jsx("label", { className: c('label'), htmlFor: id, children: label }), _jsx("select", { ...rest, className: rootClss, id: id, value: value, onChange: e => {
|
|
39
|
-
const { target } = e;
|
|
40
|
-
rest.onChange?.(e);
|
|
41
|
-
if (value === undefined)
|
|
42
|
-
return;
|
|
43
|
-
if (typeof value === 'number') {
|
|
44
|
-
target.value = `${value}`;
|
|
45
|
-
}
|
|
46
|
-
else if (typeof value === 'string') {
|
|
47
|
-
target.value = value;
|
|
48
|
-
}
|
|
49
|
-
else {
|
|
50
|
-
// value is readonly string[]
|
|
51
|
-
// not supported for <select>; ignore or normalize if needed
|
|
52
|
-
}
|
|
53
|
-
}, children: children }), isNotFalsy(error) && _jsx("span", { className: c('error'), children: error })] });
|
|
54
|
-
};
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A single parsed subtitle entry from an SRT file.
|
|
3
|
-
*
|
|
4
|
-
* @property id - Sequential subtitle number.
|
|
5
|
-
* @property start - Start time in milliseconds.
|
|
6
|
-
* @property end - End time in milliseconds.
|
|
7
|
-
* @property content - Subtitle text content.
|
|
8
|
-
*/
|
|
9
|
-
export type ParsedSub = {
|
|
10
|
-
id: number;
|
|
11
|
-
start?: number;
|
|
12
|
-
end?: number;
|
|
13
|
-
content?: string;
|
|
14
|
-
};
|
|
15
|
-
/**
|
|
16
|
-
* The inclusive ID boundaries of a subtitle group.
|
|
17
|
-
*
|
|
18
|
-
* @property startId - ID of the first subtitle in the group.
|
|
19
|
-
* @property endId - ID of the last subtitle in the group.
|
|
20
|
-
*/
|
|
21
|
-
export type SubGroupBoundaries = {
|
|
22
|
-
startId: number;
|
|
23
|
-
endId: number;
|
|
24
|
-
};
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import type { ParsedSub, SubGroupBoundaries } from './types.js';
|
|
2
|
-
/**
|
|
3
|
-
* Converts an SRT timecode (hh:mm:ss,ms) to milliseconds.
|
|
4
|
-
*
|
|
5
|
-
* @param timecode - Timecode string (e.g. '00:01:23,456').
|
|
6
|
-
* @returns The time in milliseconds.
|
|
7
|
-
*/
|
|
8
|
-
export declare const getTimecodeToMs: (timecode: string) => number;
|
|
9
|
-
/**
|
|
10
|
-
* Parses a raw SRT subtitle text into a list of {@link ParsedSub} objects.
|
|
11
|
-
*
|
|
12
|
-
* @param rawSubs - Raw subtitle content in SRT format.
|
|
13
|
-
* @returns Array of parsed subtitle entries.
|
|
14
|
-
*/
|
|
15
|
-
export declare const parseSubs: (rawSubs: string) => ParsedSub[];
|
|
16
|
-
/**
|
|
17
|
-
* Computes subtitle groups with their boundaries (startId, endId).
|
|
18
|
-
*
|
|
19
|
-
* @param subsGroups - Array of group-end subtitle IDs.
|
|
20
|
-
* @param highestSubId - Highest subtitle ID in the track.
|
|
21
|
-
* @returns Array of {@link SubGroupBoundaries}.
|
|
22
|
-
*/
|
|
23
|
-
export declare const computeSubGroupsWithBoundaries: (subsGroups: number[] | undefined, highestSubId: number) => SubGroupBoundaries[];
|
|
24
|
-
/**
|
|
25
|
-
* Returns the current subtitle group based on the last preceding subtitle ID and playback state.
|
|
26
|
-
*
|
|
27
|
-
* @param subsGroupsWithBoundaries - Array of groups with their boundaries.
|
|
28
|
-
* @param lastPrevSubId - ID of the last subtitle that has already passed.
|
|
29
|
-
* @param isEnded - Whether playback has ended.
|
|
30
|
-
* @returns The current group, or `undefined` if none matches.
|
|
31
|
-
*/
|
|
32
|
-
export declare const getCurrentGroup: (subsGroupsWithBoundaries: SubGroupBoundaries[], lastPrevSubId: number | undefined, isEnded: boolean | undefined) => SubGroupBoundaries | undefined;
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Converts an SRT timecode (hh:mm:ss,ms) to milliseconds.
|
|
3
|
-
*
|
|
4
|
-
* @param timecode - Timecode string (e.g. '00:01:23,456').
|
|
5
|
-
* @returns The time in milliseconds.
|
|
6
|
-
*/
|
|
7
|
-
export const getTimecodeToMs = (timecode) => {
|
|
8
|
-
const [hours = '0', minutes = '0', secondsAndMs = '0,0'] = timecode.split(':');
|
|
9
|
-
const [seconds = '0', milliseconds = '0'] = secondsAndMs.split(',');
|
|
10
|
-
let result = parseInt(hours) * 60 * 60 * 1000;
|
|
11
|
-
result += parseInt(minutes) * 60 * 1000;
|
|
12
|
-
result += parseInt(seconds) * 1000;
|
|
13
|
-
result += parseInt(milliseconds);
|
|
14
|
-
return result;
|
|
15
|
-
};
|
|
16
|
-
/**
|
|
17
|
-
* Parses a raw SRT subtitle text into a list of {@link ParsedSub} objects.
|
|
18
|
-
*
|
|
19
|
-
* @param rawSubs - Raw subtitle content in SRT format.
|
|
20
|
-
* @returns Array of parsed subtitle entries.
|
|
21
|
-
*/
|
|
22
|
-
export const parseSubs = (rawSubs) => {
|
|
23
|
-
const numberRegex = /^\d+$/v;
|
|
24
|
-
const timecodeRegex = /^[0-9]+:[0-9]+:[0-9]+,[0-9]+\s*-->\s*[0-9]+:[0-9]+:[0-9]+,[0-9]+$/v;
|
|
25
|
-
const parsedSubs = [];
|
|
26
|
-
rawSubs.split('\n').forEach(line => {
|
|
27
|
-
if (line.trim() === '')
|
|
28
|
-
return;
|
|
29
|
-
const lastParsedSub = parsedSubs[parsedSubs.length - 1];
|
|
30
|
-
const matchId = line.match(numberRegex);
|
|
31
|
-
const matchTimecode = line.match(timecodeRegex);
|
|
32
|
-
// id
|
|
33
|
-
if (matchId !== null) {
|
|
34
|
-
if (lastParsedSub === undefined
|
|
35
|
-
|| lastParsedSub.content !== undefined) {
|
|
36
|
-
const parsedSub = { id: parseInt(line) };
|
|
37
|
-
parsedSubs.push(parsedSub);
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
// timecode
|
|
42
|
-
if (matchTimecode !== null) {
|
|
43
|
-
if (lastParsedSub?.id !== undefined) {
|
|
44
|
-
const [rawStart = '', rawEnd = ''] = line.split('-->');
|
|
45
|
-
const startTime = rawStart.trim();
|
|
46
|
-
const endTime = rawEnd.trim();
|
|
47
|
-
lastParsedSub.start = getTimecodeToMs(startTime);
|
|
48
|
-
lastParsedSub.end = getTimecodeToMs(endTime);
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
// content
|
|
53
|
-
if (lastParsedSub?.id !== undefined
|
|
54
|
-
&& lastParsedSub.start !== undefined
|
|
55
|
-
&& lastParsedSub.end !== undefined) {
|
|
56
|
-
if (lastParsedSub.content !== undefined) {
|
|
57
|
-
lastParsedSub.content += `\n${line}`;
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
lastParsedSub.content = line;
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
return parsedSubs;
|
|
64
|
-
};
|
|
65
|
-
/**
|
|
66
|
-
* Computes subtitle groups with their boundaries (startId, endId).
|
|
67
|
-
*
|
|
68
|
-
* @param subsGroups - Array of group-end subtitle IDs.
|
|
69
|
-
* @param highestSubId - Highest subtitle ID in the track.
|
|
70
|
-
* @returns Array of {@link SubGroupBoundaries}.
|
|
71
|
-
*/
|
|
72
|
-
export const computeSubGroupsWithBoundaries = (subsGroups, highestSubId) => {
|
|
73
|
-
const fallback = [{ startId: 1, endId: highestSubId }];
|
|
74
|
-
if (subsGroups === undefined || subsGroups.length === 0)
|
|
75
|
-
return fallback;
|
|
76
|
-
const emptySubGroupBoundaries = [];
|
|
77
|
-
return subsGroups.reduce((acc, curr, currIndex) => {
|
|
78
|
-
const lastInAcc = acc[acc.length - 1];
|
|
79
|
-
const startId = lastInAcc === undefined ? 1 : lastInAcc.endId + 1;
|
|
80
|
-
const endId = curr;
|
|
81
|
-
if (currIndex === subsGroups.length - 1
|
|
82
|
-
&& endId !== highestSubId) {
|
|
83
|
-
return [
|
|
84
|
-
...acc,
|
|
85
|
-
{ startId, endId },
|
|
86
|
-
{ startId: endId + 1, endId: highestSubId }
|
|
87
|
-
];
|
|
88
|
-
}
|
|
89
|
-
return [...acc, { startId, endId }];
|
|
90
|
-
}, emptySubGroupBoundaries);
|
|
91
|
-
};
|
|
92
|
-
/**
|
|
93
|
-
* Returns the current subtitle group based on the last preceding subtitle ID and playback state.
|
|
94
|
-
*
|
|
95
|
-
* @param subsGroupsWithBoundaries - Array of groups with their boundaries.
|
|
96
|
-
* @param lastPrevSubId - ID of the last subtitle that has already passed.
|
|
97
|
-
* @param isEnded - Whether playback has ended.
|
|
98
|
-
* @returns The current group, or `undefined` if none matches.
|
|
99
|
-
*/
|
|
100
|
-
export const getCurrentGroup = (subsGroupsWithBoundaries, lastPrevSubId, isEnded) => {
|
|
101
|
-
const previousGroups = subsGroupsWithBoundaries.filter(group => group.startId <= (lastPrevSubId ?? 0));
|
|
102
|
-
if (previousGroups.length === 0)
|
|
103
|
-
return isEnded === true
|
|
104
|
-
? subsGroupsWithBoundaries[subsGroupsWithBoundaries.length - 1]
|
|
105
|
-
: subsGroupsWithBoundaries[0];
|
|
106
|
-
return previousGroups[previousGroups.length - 1];
|
|
107
|
-
};
|