@es-joy/jsoe 0.16.0 → 0.17.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/.ncurc.cjs +4 -5
- package/CHANGES.md +4 -0
- package/README.md +27 -3
- package/badges/licenses-badge.svg +1 -0
- package/dist/formatAndTypeChoices.d.ts +39 -19
- package/dist/formatAndTypeChoices.d.ts.map +1 -1
- package/dist/formats/indexedDBKey.d.ts +1 -1
- package/dist/formats/indexedDBKey.d.ts.map +1 -1
- package/dist/formats/json.d.ts +1 -1
- package/dist/formats/json.d.ts.map +1 -1
- package/dist/formats/schema.d.ts +11 -0
- package/dist/formats/schema.d.ts.map +1 -0
- package/dist/formats/structuredCloning.d.ts +11 -13
- package/dist/formats/structuredCloning.d.ts.map +1 -1
- package/dist/formats.d.ts +86 -25
- package/dist/formats.d.ts.map +1 -1
- package/dist/fundamentalTypes/BooleanObjectType.d.ts +1 -1
- package/dist/fundamentalTypes/BooleanObjectType.d.ts.map +1 -1
- package/dist/fundamentalTypes/NumberObjectType.d.ts +1 -1
- package/dist/fundamentalTypes/NumberObjectType.d.ts.map +1 -1
- package/dist/fundamentalTypes/StringObjectType.d.ts +1 -1
- package/dist/fundamentalTypes/StringObjectType.d.ts.map +1 -1
- package/dist/fundamentalTypes/arrayReferenceType.d.ts +1 -1
- package/dist/fundamentalTypes/arrayType.d.ts +3 -3
- package/dist/fundamentalTypes/arrayType.d.ts.map +1 -1
- package/dist/fundamentalTypes/bigintObjectType.d.ts +6 -0
- package/dist/fundamentalTypes/bigintObjectType.d.ts.map +1 -0
- package/dist/fundamentalTypes/bigintType.d.ts +1 -1
- package/dist/fundamentalTypes/bigintType.d.ts.map +1 -1
- package/dist/fundamentalTypes/blobType.d.ts +1 -1
- package/dist/fundamentalTypes/blobType.d.ts.map +1 -1
- package/dist/fundamentalTypes/booleanType.d.ts +8 -0
- package/dist/fundamentalTypes/booleanType.d.ts.map +1 -0
- package/dist/fundamentalTypes/catchType.d.ts +6 -0
- package/dist/fundamentalTypes/catchType.d.ts.map +1 -0
- package/dist/fundamentalTypes/dateType.d.ts +4 -4
- package/dist/fundamentalTypes/dateType.d.ts.map +1 -1
- package/dist/fundamentalTypes/domexceptionType.d.ts +1 -1
- package/dist/fundamentalTypes/domexceptionType.d.ts.map +1 -1
- package/dist/fundamentalTypes/enumType.d.ts +6 -0
- package/dist/fundamentalTypes/enumType.d.ts.map +1 -0
- package/dist/fundamentalTypes/errorType.d.ts +1 -1
- package/dist/fundamentalTypes/errorType.d.ts.map +1 -1
- package/dist/fundamentalTypes/fileType.d.ts +1 -1
- package/dist/fundamentalTypes/fileType.d.ts.map +1 -1
- package/dist/fundamentalTypes/filelistType.d.ts +1 -1
- package/dist/fundamentalTypes/filelistType.d.ts.map +1 -1
- package/dist/fundamentalTypes/functionType.d.ts +6 -0
- package/dist/fundamentalTypes/functionType.d.ts.map +1 -0
- package/dist/fundamentalTypes/literalType.d.ts +6 -0
- package/dist/fundamentalTypes/literalType.d.ts.map +1 -0
- package/dist/fundamentalTypes/mapType.d.ts +1 -1
- package/dist/fundamentalTypes/mapType.d.ts.map +1 -1
- package/dist/fundamentalTypes/nanType.d.ts +6 -0
- package/dist/fundamentalTypes/nanType.d.ts.map +1 -0
- package/dist/fundamentalTypes/nativeEnumType.d.ts +6 -0
- package/dist/fundamentalTypes/nativeEnumType.d.ts.map +1 -0
- package/dist/fundamentalTypes/neverType.d.ts +6 -0
- package/dist/fundamentalTypes/neverType.d.ts.map +1 -0
- package/dist/fundamentalTypes/noneditableType.d.ts +1 -1
- package/dist/fundamentalTypes/noneditableType.d.ts.map +1 -1
- package/dist/fundamentalTypes/nullType.d.ts +1 -1
- package/dist/fundamentalTypes/nullType.d.ts.map +1 -1
- package/dist/fundamentalTypes/numberType.d.ts +1 -1
- package/dist/fundamentalTypes/numberType.d.ts.map +1 -1
- package/dist/fundamentalTypes/objectReferenceType.d.ts +1 -1
- package/dist/fundamentalTypes/objectType.d.ts +1 -1
- package/dist/fundamentalTypes/objectType.d.ts.map +1 -1
- package/dist/fundamentalTypes/promiseType.d.ts +6 -0
- package/dist/fundamentalTypes/promiseType.d.ts.map +1 -0
- package/dist/fundamentalTypes/recordType.d.ts +6 -0
- package/dist/fundamentalTypes/recordType.d.ts.map +1 -0
- package/dist/fundamentalTypes/regexpType.d.ts +1 -1
- package/dist/fundamentalTypes/regexpType.d.ts.map +1 -1
- package/dist/fundamentalTypes/setType.d.ts +1 -1
- package/dist/fundamentalTypes/setType.d.ts.map +1 -1
- package/dist/fundamentalTypes/sparseUndefinedType.d.ts +1 -1
- package/dist/fundamentalTypes/sparseUndefinedType.d.ts.map +1 -1
- package/dist/fundamentalTypes/stringType.d.ts +1 -1
- package/dist/fundamentalTypes/stringType.d.ts.map +1 -1
- package/dist/fundamentalTypes/symbolType.d.ts +8 -0
- package/dist/fundamentalTypes/symbolType.d.ts.map +1 -0
- package/dist/fundamentalTypes/tupleType.d.ts +6 -0
- package/dist/fundamentalTypes/tupleType.d.ts.map +1 -0
- package/dist/fundamentalTypes/undefinedType.d.ts +1 -1
- package/dist/fundamentalTypes/undefinedType.d.ts.map +1 -1
- package/dist/fundamentalTypes/voidType.d.ts +6 -0
- package/dist/fundamentalTypes/voidType.d.ts.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9660 -1586
- package/dist/subTypes/blobHTMLType.d.ts.map +1 -1
- package/dist/subTypes/falseType.d.ts +1 -1
- package/dist/subTypes/trueType.d.ts +1 -1
- package/dist/superTypes/SpecialNumberType.d.ts +1 -1
- package/dist/superTypes/SpecialRealNumberType.d.ts +1 -1
- package/dist/superTypes/SpecialRealNumberType.d.ts.map +1 -1
- package/dist/superTypes/buffersourceType.d.ts +1 -1
- package/dist/superTypes/buffersourceType.d.ts.map +1 -1
- package/dist/superTypes/dommatrixType.d.ts +1 -1
- package/dist/superTypes/dommatrixType.d.ts.map +1 -1
- package/dist/superTypes/dompointType.d.ts +1 -1
- package/dist/superTypes/dompointType.d.ts.map +1 -1
- package/dist/superTypes/domrectType.d.ts +1 -1
- package/dist/superTypes/domrectType.d.ts.map +1 -1
- package/dist/superTypes/errorsSpecialType.d.ts +1 -1
- package/dist/superTypes/errorsSpecialType.d.ts.map +1 -1
- package/dist/typeChoices.d.ts +33 -16
- package/dist/typeChoices.d.ts.map +1 -1
- package/dist/types.d.ts +161 -157
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/dialogs.d.ts +3 -3
- package/dist/utils/dialogs.d.ts.map +1 -1
- package/dist/utils/jsonPointer.d.ts.map +1 -1
- package/dist/utils/media.d.ts.map +1 -1
- package/dist/utils/objects.d.ts +16 -0
- package/dist/utils/objects.d.ts.map +1 -0
- package/dist/utils/types.d.ts +1 -1
- package/dist/utils/types.d.ts.map +1 -1
- package/dist/vendor-imports.d.ts +1 -1
- package/eslint.config.js +74 -0
- package/licenseInfo.json +4 -0
- package/package.json +33 -42
- package/rollup.config.js +15 -0
- package/src/formatAndTypeChoices.js +68 -54
- package/src/formats/indexedDBKey.js +9 -4
- package/src/formats/json.js +7 -4
- package/src/formats/schema.js +772 -0
- package/src/formats/structuredCloning.js +187 -86
- package/src/formats.js +61 -26
- package/src/fundamentalTypes/BooleanObjectType.js +18 -6
- package/src/fundamentalTypes/NumberObjectType.js +18 -5
- package/src/fundamentalTypes/StringObjectType.js +20 -8
- package/src/fundamentalTypes/arrayType.js +1241 -533
- package/src/fundamentalTypes/bigintObjectType.js +64 -0
- package/src/fundamentalTypes/bigintType.js +31 -5
- package/src/fundamentalTypes/blobType.js +201 -190
- package/src/fundamentalTypes/booleanType.js +63 -0
- package/src/fundamentalTypes/catchType.js +140 -0
- package/src/fundamentalTypes/dateType.js +57 -19
- package/src/fundamentalTypes/domexceptionType.js +61 -63
- package/src/fundamentalTypes/enumType.js +52 -0
- package/src/fundamentalTypes/errorType.js +20 -7
- package/src/fundamentalTypes/fileType.js +195 -189
- package/src/fundamentalTypes/filelistType.js +4 -0
- package/src/fundamentalTypes/functionType.js +150 -0
- package/src/fundamentalTypes/literalType.js +81 -0
- package/src/fundamentalTypes/mapType.js +4 -0
- package/src/fundamentalTypes/nanType.js +41 -0
- package/src/fundamentalTypes/nativeEnumType.js +155 -0
- package/src/fundamentalTypes/neverType.js +44 -0
- package/src/fundamentalTypes/noneditableType.js +19 -5
- package/src/fundamentalTypes/nullType.js +16 -6
- package/src/fundamentalTypes/numberType.js +49 -6
- package/src/fundamentalTypes/objectType.js +10 -2
- package/src/fundamentalTypes/promiseType.js +60 -0
- package/src/fundamentalTypes/recordType.js +42 -0
- package/src/fundamentalTypes/regexpType.js +51 -33
- package/src/fundamentalTypes/setType.js +4 -0
- package/src/fundamentalTypes/sparseUndefinedType.js +3 -0
- package/src/fundamentalTypes/stringType.js +254 -6
- package/src/fundamentalTypes/symbolType.js +81 -0
- package/src/fundamentalTypes/tupleType.js +39 -0
- package/src/fundamentalTypes/undefinedType.js +14 -4
- package/src/fundamentalTypes/voidType.js +48 -0
- package/src/jsoe.css +37 -3
- package/src/subTypes/blobHTMLType.js +33 -24
- package/src/superTypes/SpecialRealNumberType.js +22 -6
- package/src/superTypes/buffersourceType.js +86 -30
- package/src/superTypes/dommatrixType.js +24 -7
- package/src/superTypes/dompointType.js +27 -7
- package/src/superTypes/domrectType.js +33 -7
- package/src/superTypes/errorsSpecialType.js +30 -14
- package/src/typeChoices.js +115 -44
- package/src/types.js +129 -45
- package/src/utils/FileList.js +3 -3
- package/src/utils/dialogs.js +6 -8
- package/src/utils/objects.js +22 -0
- package/src/vendor-imports.js +1 -1
- package/tsconfig.json +2 -2
- package/vendor/jamilih/dist/jml-es.js +23 -6
- package/vendor/typeson-registry/dist/index.js +77 -47
- package/vendor/zod/lib/index.mjs +4236 -0
- package/vendor/zodex/dist/esm/dezerialize.d.ts +26 -0
- package/vendor/zodex/dist/esm/dezerialize.js +393 -0
- package/vendor/zodex/dist/esm/index.d.ts +9 -0
- package/vendor/zodex/dist/esm/index.js +4 -0
- package/vendor/zodex/dist/esm/infer.d.ts +29 -0
- package/vendor/zodex/dist/esm/infer.js +1 -0
- package/vendor/zodex/dist/esm/package.json +1 -0
- package/vendor/zodex/dist/esm/types.d.ts +201 -0
- package/vendor/zodex/dist/esm/types.js +13 -0
- package/vendor/zodex/dist/esm/ui.d.ts +23 -0
- package/vendor/zodex/dist/esm/ui.js +10 -0
- package/vendor/zodex/dist/esm/zerialize.d.ts +50 -0
- package/vendor/zodex/dist/esm/zerialize.js +417 -0
- package/vendor/zodex/dist/esm/zod-types.d.ts +11 -0
- package/vendor/zodex/dist/esm/zod-types.js +1 -0
- package/.eslintignore +0 -13
- package/.eslintrc.cjs +0 -145
- package/.nyc_output/out.json +0 -117370
- package/cypress.config.ts +0 -15
- package/demo/index-instrumented.html +0 -29
- package/demo/index-instrumented.js +0 -644
- package/demo/index.html +0 -29
- package/demo/index.js +0 -215
- package/src/formats/schemaAndArbitrary.js +0 -20
- package/src/formats/schemaOnly.js +0 -539
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {jml} from '../vendor-imports.js';
|
|
1
|
+
import {jml, toStringTag} from '../vendor-imports.js';
|
|
2
2
|
import {$e} from '../utils/templateUtils.js';
|
|
3
3
|
import {visualize, getUserMedia, startScreenCapture} from '../utils/media.js';
|
|
4
4
|
import dialogs from '../utils/dialogs.js';
|
|
@@ -168,6 +168,9 @@ function binaryButton (value, editable) {
|
|
|
168
168
|
const fileType = {
|
|
169
169
|
option: ['File'],
|
|
170
170
|
stringRegex: /^File\((.*)\)$/u,
|
|
171
|
+
valueMatch (x) {
|
|
172
|
+
return toStringTag(x) === 'File';
|
|
173
|
+
},
|
|
171
174
|
toValue (s) {
|
|
172
175
|
const obj = JSON.parse(s);
|
|
173
176
|
return {value: new File([obj.stringContents], obj.name, {
|
|
@@ -189,10 +192,13 @@ const fileType = {
|
|
|
189
192
|
this.getInput({root})
|
|
190
193
|
).$value;
|
|
191
194
|
},
|
|
192
|
-
viewUI ({value}) {
|
|
195
|
+
viewUI ({value, specificSchemaObject}) {
|
|
193
196
|
return ['div', {dataset: {type: 'file'}}, [
|
|
194
|
-
['b', {
|
|
195
|
-
'
|
|
197
|
+
['b', {
|
|
198
|
+
class: 'emphasis',
|
|
199
|
+
title: specificSchemaObject?.description ? '(a File)' : undefined
|
|
200
|
+
}, [
|
|
201
|
+
specificSchemaObject?.description ?? 'File'
|
|
196
202
|
]],
|
|
197
203
|
['br'],
|
|
198
204
|
['br'],
|
|
@@ -218,7 +224,7 @@ const fileType = {
|
|
|
218
224
|
['br'],
|
|
219
225
|
value.type.startsWith('text/') || value.type === 'application/json'
|
|
220
226
|
? (() => {
|
|
221
|
-
const div =
|
|
227
|
+
const div = jml('div');
|
|
222
228
|
const reader = new FileReader();
|
|
223
229
|
reader.addEventListener('load', function () {
|
|
224
230
|
div.append(jml('div', [
|
|
@@ -250,7 +256,7 @@ const fileType = {
|
|
|
250
256
|
value.type.startsWith('video/')
|
|
251
257
|
? (() => {
|
|
252
258
|
const objURL = URL.createObjectURL(value);
|
|
253
|
-
const video =
|
|
259
|
+
const video = jml('video', {
|
|
254
260
|
src: objURL,
|
|
255
261
|
class: 'video',
|
|
256
262
|
$on: {
|
|
@@ -258,7 +264,7 @@ const fileType = {
|
|
|
258
264
|
URL.revokeObjectURL(objURL);
|
|
259
265
|
}
|
|
260
266
|
}
|
|
261
|
-
})
|
|
267
|
+
});
|
|
262
268
|
|
|
263
269
|
return ['div', [
|
|
264
270
|
video,
|
|
@@ -303,7 +309,7 @@ const fileType = {
|
|
|
303
309
|
value.type.startsWith('audio/')
|
|
304
310
|
? (() => {
|
|
305
311
|
const objURL = URL.createObjectURL(value);
|
|
306
|
-
const audio =
|
|
312
|
+
const audio = jml('audio', {
|
|
307
313
|
src: objURL,
|
|
308
314
|
class: 'audio',
|
|
309
315
|
$on: {
|
|
@@ -311,7 +317,7 @@ const fileType = {
|
|
|
311
317
|
URL.revokeObjectURL(objURL);
|
|
312
318
|
}
|
|
313
319
|
}
|
|
314
|
-
})
|
|
320
|
+
});
|
|
315
321
|
return ['div', [
|
|
316
322
|
audio,
|
|
317
323
|
['button', {
|
|
@@ -382,10 +388,13 @@ const fileType = {
|
|
|
382
388
|
: ''
|
|
383
389
|
]];
|
|
384
390
|
},
|
|
385
|
-
editUI ({typeNamespace, value = {}}) {
|
|
391
|
+
editUI ({typeNamespace, specificSchemaObject, value = {}}) {
|
|
386
392
|
// Todo: Could add way to preview file in edit mode (whether
|
|
387
393
|
// recorded or uploaded)
|
|
388
|
-
return ['div', {
|
|
394
|
+
return ['div', {
|
|
395
|
+
dataset: {type: 'file'},
|
|
396
|
+
title: specificSchemaObject?.description ?? 'File'
|
|
397
|
+
}, [
|
|
389
398
|
['fieldset', {
|
|
390
399
|
class: 'fileMetaData',
|
|
391
400
|
$custom: {
|
|
@@ -456,7 +465,7 @@ const fileType = {
|
|
|
456
465
|
['label', [
|
|
457
466
|
'Size (in bytes) ',
|
|
458
467
|
['input', {
|
|
459
|
-
type: 'number', disabled: true, class: 'size',
|
|
468
|
+
type: 'number', step: '1', disabled: true, class: 'size',
|
|
460
469
|
value: String(value.size)
|
|
461
470
|
}]
|
|
462
471
|
]],
|
|
@@ -576,194 +585,192 @@ const fileType = {
|
|
|
576
585
|
'Supply file through recording'
|
|
577
586
|
]],
|
|
578
587
|
(() => {
|
|
579
|
-
const select =
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
);
|
|
588
|
+
const select = jml('select', {
|
|
589
|
+
class: 'device',
|
|
590
|
+
$on: {
|
|
591
|
+
async change () {
|
|
592
|
+
const videoContainer = /** @type {HTMLDivElement} */ (
|
|
593
|
+
this.nextElementSibling?.nextElementSibling
|
|
594
|
+
);
|
|
587
595
|
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
const oldVideo =
|
|
596
|
-
/**
|
|
597
|
-
* @type {HTMLVideoElement & {
|
|
598
|
-
* $stream: MediaStream
|
|
599
|
-
* }}
|
|
600
|
-
*/
|
|
601
|
-
($e(
|
|
602
|
-
videoContainer,
|
|
603
|
-
'video.previewMedia'
|
|
604
|
-
));
|
|
605
|
-
|
|
606
|
-
// Drop preexisting listeners
|
|
607
|
-
const previewMedia =
|
|
608
|
-
/**
|
|
609
|
-
* @type {HTMLVideoElement & {
|
|
610
|
-
* $stream: MediaStream,
|
|
611
|
-
* $screenShare: boolean
|
|
612
|
-
* }}
|
|
613
|
-
*/ (
|
|
614
|
-
jml('video', {
|
|
615
|
-
class: 'previewMedia'
|
|
616
|
-
})
|
|
617
|
-
);
|
|
618
|
-
|
|
619
|
-
if (oldVideo.$stream) {
|
|
620
|
-
const tracks = /** @type {MediaStream} */ (
|
|
621
|
-
oldVideo.$stream
|
|
622
|
-
).getTracks();
|
|
623
|
-
tracks.forEach((track) => {
|
|
624
|
-
track.stop();
|
|
625
|
-
});
|
|
626
|
-
oldVideo.srcObject = null;
|
|
627
|
-
}
|
|
596
|
+
const photo =
|
|
597
|
+
/**
|
|
598
|
+
* @type {HTMLCanvasElement}
|
|
599
|
+
*/
|
|
600
|
+
($e(videoContainer, 'img.photo'));
|
|
601
|
+
photo.hidden = true;
|
|
628
602
|
|
|
629
|
-
|
|
603
|
+
const oldVideo =
|
|
604
|
+
/**
|
|
605
|
+
* @type {HTMLVideoElement & {
|
|
606
|
+
* $stream: MediaStream
|
|
607
|
+
* }}
|
|
608
|
+
*/
|
|
609
|
+
($e(
|
|
610
|
+
videoContainer,
|
|
611
|
+
'video.previewMedia'
|
|
612
|
+
));
|
|
630
613
|
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
614
|
+
// Drop preexisting listeners
|
|
615
|
+
const previewMedia =
|
|
616
|
+
/**
|
|
617
|
+
* @type {HTMLVideoElement & {
|
|
618
|
+
* $stream: MediaStream,
|
|
619
|
+
* $screenShare: boolean
|
|
620
|
+
* }}
|
|
621
|
+
*/ (
|
|
622
|
+
jml('video', {
|
|
623
|
+
class: 'previewMedia'
|
|
624
|
+
})
|
|
635
625
|
);
|
|
636
626
|
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
)
|
|
627
|
+
if (oldVideo.$stream) {
|
|
628
|
+
const tracks = /** @type {MediaStream} */ (
|
|
629
|
+
oldVideo.$stream
|
|
630
|
+
).getTracks();
|
|
631
|
+
tracks.forEach((track) => {
|
|
632
|
+
track.stop();
|
|
633
|
+
});
|
|
634
|
+
oldVideo.srcObject = null;
|
|
635
|
+
}
|
|
642
636
|
|
|
643
|
-
|
|
644
|
-
/** @type {HTMLDivElement} */
|
|
645
|
-
(select.nextElementSibling?.
|
|
646
|
-
nextElementSibling),
|
|
647
|
-
'div.recordedMedia'
|
|
648
|
-
)).hidden = true;
|
|
637
|
+
oldVideo.replaceWith(previewMedia);
|
|
649
638
|
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
639
|
+
const takeSnapshot = /** @type {HTMLButtonElement} */ (
|
|
640
|
+
$e(/** @type {HTMLDivElement} */ (
|
|
641
|
+
select.nextElementSibling
|
|
642
|
+
), '.takeSnapshot')
|
|
643
|
+
);
|
|
653
644
|
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
*/
|
|
660
|
-
let constraints;
|
|
661
|
-
let screenShareConstraints;
|
|
662
|
-
|
|
663
|
-
previewMedia.$screenShare = false;
|
|
664
|
-
switch (select.value) {
|
|
665
|
-
case 'audio-and-video':
|
|
666
|
-
constraints = {video: true, audio: true};
|
|
667
|
-
previewMedia.hidden = false;
|
|
668
|
-
takeSnapshot.hidden = false;
|
|
669
|
-
recordMedia.textContent = 'Record video/audio';
|
|
670
|
-
break;
|
|
671
|
-
case 'video':
|
|
672
|
-
constraints = {video: true};
|
|
673
|
-
previewMedia.hidden = false;
|
|
674
|
-
takeSnapshot.hidden = false;
|
|
675
|
-
recordMedia.textContent = 'Record video';
|
|
676
|
-
break;
|
|
677
|
-
case 'audio':
|
|
678
|
-
constraints = {audio: true};
|
|
679
|
-
previewMedia.hidden = true;
|
|
680
|
-
takeSnapshot.hidden = true;
|
|
681
|
-
recordMedia.textContent = 'Record audio';
|
|
682
|
-
break;
|
|
683
|
-
case 'screenShare':
|
|
684
|
-
screenShareConstraints = {video: true};
|
|
685
|
-
// Fallthrough
|
|
686
|
-
case 'screenShareAndVideo':
|
|
687
|
-
if (!screenShareConstraints) {
|
|
688
|
-
screenShareConstraints = {video: true, audio: true};
|
|
689
|
-
}
|
|
690
|
-
previewMedia.$screenShare = true;
|
|
691
|
-
previewMedia.hidden = true;
|
|
692
|
-
takeSnapshot.hidden = true;
|
|
693
|
-
visualizer.hidden = true;
|
|
694
|
-
break;
|
|
695
|
-
default:
|
|
696
|
-
return;
|
|
697
|
-
}
|
|
645
|
+
const recordMedia = /** @type {HTMLButtonElement} */ (
|
|
646
|
+
$e(/** @type {HTMLDivElement} */ (
|
|
647
|
+
select.nextElementSibling
|
|
648
|
+
), '.recordMedia')
|
|
649
|
+
);
|
|
698
650
|
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
}
|
|
651
|
+
/** @type {HTMLDivElement} */ ($e(
|
|
652
|
+
/** @type {HTMLDivElement} */
|
|
653
|
+
(select.nextElementSibling?.
|
|
654
|
+
nextElementSibling),
|
|
655
|
+
'div.recordedMedia'
|
|
656
|
+
)).hidden = true;
|
|
706
657
|
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
// Save as stream for later reuse as stream
|
|
711
|
-
previewMedia.$stream = mediaStream;
|
|
712
|
-
|
|
713
|
-
if (constraints.video) {
|
|
714
|
-
const canvas =
|
|
715
|
-
/**
|
|
716
|
-
* @type {HTMLCanvasElement}
|
|
717
|
-
*/
|
|
718
|
-
($e(
|
|
719
|
-
videoContainer,
|
|
720
|
-
'canvas.recordedImage'
|
|
721
|
-
));
|
|
722
|
-
// https://developer.mozilla.org/en-US/docs/Web/API/Media_Capture_and_Streams_API/Taking_still_photos
|
|
723
|
-
previewMedia.addEventListener('canplay', () => {
|
|
724
|
-
canvas.setAttribute('width', String(
|
|
725
|
-
previewMedia.videoWidth
|
|
726
|
-
));
|
|
727
|
-
canvas.setAttribute(
|
|
728
|
-
'height', String(previewMedia.videoHeight)
|
|
729
|
-
);
|
|
730
|
-
});
|
|
731
|
-
}
|
|
658
|
+
const visualizer = /** @type {HTMLCanvasElement} */ (
|
|
659
|
+
$e(videoContainer, 'canvas.visualizer')
|
|
660
|
+
);
|
|
732
661
|
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
662
|
+
/**
|
|
663
|
+
* @type {{
|
|
664
|
+
* video?: true,
|
|
665
|
+
* audio?: true
|
|
666
|
+
* }|undefined}
|
|
667
|
+
*/
|
|
668
|
+
let constraints;
|
|
669
|
+
let screenShareConstraints;
|
|
670
|
+
|
|
671
|
+
previewMedia.$screenShare = false;
|
|
672
|
+
switch (select.value) {
|
|
673
|
+
case 'audio-and-video':
|
|
674
|
+
constraints = {video: true, audio: true};
|
|
675
|
+
previewMedia.hidden = false;
|
|
676
|
+
takeSnapshot.hidden = false;
|
|
677
|
+
recordMedia.textContent = 'Record video/audio';
|
|
678
|
+
break;
|
|
679
|
+
case 'video':
|
|
680
|
+
constraints = {video: true};
|
|
681
|
+
previewMedia.hidden = false;
|
|
682
|
+
takeSnapshot.hidden = false;
|
|
683
|
+
recordMedia.textContent = 'Record video';
|
|
684
|
+
break;
|
|
685
|
+
case 'audio':
|
|
686
|
+
constraints = {audio: true};
|
|
687
|
+
previewMedia.hidden = true;
|
|
688
|
+
takeSnapshot.hidden = true;
|
|
689
|
+
recordMedia.textContent = 'Record audio';
|
|
690
|
+
break;
|
|
691
|
+
case 'screenShare':
|
|
692
|
+
screenShareConstraints = {video: true};
|
|
693
|
+
// Fallthrough
|
|
694
|
+
case 'screenShareAndVideo':
|
|
695
|
+
if (!screenShareConstraints) {
|
|
696
|
+
screenShareConstraints = {video: true, audio: true};
|
|
697
|
+
}
|
|
698
|
+
previewMedia.$screenShare = true;
|
|
699
|
+
previewMedia.hidden = true;
|
|
700
|
+
takeSnapshot.hidden = true;
|
|
701
|
+
visualizer.hidden = true;
|
|
702
|
+
break;
|
|
703
|
+
default:
|
|
704
|
+
return;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
if (constraints) {
|
|
708
|
+
const mediaStream = await getUserMedia(constraints);
|
|
709
|
+
/* istanbul ignore if */
|
|
710
|
+
if (!mediaStream) {
|
|
711
|
+
await dialogs.alert('Error getting user media');
|
|
712
|
+
return;
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
videoContainer.hidden = false;
|
|
716
|
+
previewMedia.srcObject = mediaStream;
|
|
717
|
+
|
|
718
|
+
// Save as stream for later reuse as stream
|
|
719
|
+
previewMedia.$stream = mediaStream;
|
|
720
|
+
|
|
721
|
+
if (constraints.video) {
|
|
722
|
+
const canvas =
|
|
723
|
+
/**
|
|
724
|
+
* @type {HTMLCanvasElement}
|
|
725
|
+
*/
|
|
726
|
+
($e(
|
|
727
|
+
videoContainer,
|
|
728
|
+
'canvas.recordedImage'
|
|
729
|
+
));
|
|
730
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/Media_Capture_and_Streams_API/Taking_still_photos
|
|
731
|
+
previewMedia.addEventListener('canplay', () => {
|
|
732
|
+
canvas.setAttribute('width', String(
|
|
733
|
+
previewMedia.videoWidth
|
|
734
|
+
));
|
|
735
|
+
canvas.setAttribute(
|
|
736
|
+
'height', String(previewMedia.videoHeight)
|
|
737
|
+
);
|
|
744
738
|
});
|
|
745
|
-
}
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
);
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
previewMedia.addEventListener('loadedmetadata', () => {
|
|
742
|
+
previewMedia.play();
|
|
743
|
+
if (constraints?.audio) {
|
|
744
|
+
visualizer.hidden = false;
|
|
745
|
+
visualize(
|
|
746
|
+
mediaStream,
|
|
747
|
+
visualizer
|
|
748
|
+
);
|
|
749
|
+
} else {
|
|
750
|
+
visualizer.hidden = true;
|
|
753
751
|
}
|
|
752
|
+
});
|
|
753
|
+
} else if (screenShareConstraints) {
|
|
754
|
+
const mediaStream = await startScreenCapture(
|
|
755
|
+
screenShareConstraints
|
|
756
|
+
);
|
|
757
|
+
/* istanbul ignore if */
|
|
758
|
+
if (!mediaStream) {
|
|
759
|
+
await dialogs.alert('Error getting user media');
|
|
760
|
+
return;
|
|
761
|
+
}
|
|
754
762
|
|
|
755
|
-
|
|
756
|
-
|
|
763
|
+
videoContainer.hidden = false;
|
|
764
|
+
previewMedia.srcObject = mediaStream;
|
|
757
765
|
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
}
|
|
766
|
+
// Save as stream for later reuse as stream
|
|
767
|
+
previewMedia.$stream = mediaStream;
|
|
761
768
|
}
|
|
762
769
|
}
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
]
|
|
766
|
-
);
|
|
770
|
+
}
|
|
771
|
+
}, [
|
|
772
|
+
['option', {value: ''}, ['Please choose a device']]
|
|
773
|
+
]);
|
|
767
774
|
|
|
768
775
|
(async () => {
|
|
769
776
|
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
@@ -864,8 +871,7 @@ const fileType = {
|
|
|
864
871
|
|
|
865
872
|
try {
|
|
866
873
|
mediaRecorder.start();
|
|
867
|
-
/* istanbul ignore
|
|
868
|
-
} catch (err) {
|
|
874
|
+
} catch /* istanbul ignore next */ {
|
|
869
875
|
dialogs.alert('Error starting media recorder');
|
|
870
876
|
return;
|
|
871
877
|
}
|
|
@@ -1009,9 +1015,9 @@ const fileType = {
|
|
|
1009
1015
|
dialogs.alert('Error converting canvas to Blob');
|
|
1010
1016
|
return;
|
|
1011
1017
|
}
|
|
1012
|
-
const newPhoto =
|
|
1018
|
+
const newPhoto = jml('img', {
|
|
1013
1019
|
class: 'photo'
|
|
1014
|
-
})
|
|
1020
|
+
});
|
|
1015
1021
|
const url = URL.createObjectURL(blob);
|
|
1016
1022
|
|
|
1017
1023
|
newPhoto.addEventListener('load', () => {
|
|
@@ -1058,9 +1064,9 @@ const fileType = {
|
|
|
1058
1064
|
{class: 'recordedMedia'},
|
|
1059
1065
|
/** @type {import('jamilih').JamilihChildren} */ ([
|
|
1060
1066
|
...(() => {
|
|
1061
|
-
const recordedMedia =
|
|
1067
|
+
const recordedMedia = jml(
|
|
1062
1068
|
'video', {class: 'recordedMedia'}
|
|
1063
|
-
)
|
|
1069
|
+
);
|
|
1064
1070
|
return [
|
|
1065
1071
|
recordedMedia,
|
|
1066
1072
|
['br'],
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import {toStringTag} from '../vendor-imports.js';
|
|
1
2
|
import arrayType from './arrayType.js';
|
|
2
3
|
|
|
3
4
|
/**
|
|
@@ -10,6 +11,9 @@ const filelistType = {
|
|
|
10
11
|
regexEndings: [',', ')'],
|
|
11
12
|
stringRegexBegin: /^FileList\(/u,
|
|
12
13
|
stringRegexEnd: /^\)/u,
|
|
14
|
+
valueMatch (x) {
|
|
15
|
+
return toStringTag(x) === 'FileList';
|
|
16
|
+
},
|
|
13
17
|
|
|
14
18
|
toValue (...args) {
|
|
15
19
|
return /** @type {import('../types.js').ToValue} */ (
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import {$e} from '../utils/templateUtils.js';
|
|
2
|
+
import {copyObject} from '../utils/objects.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @type {import('../types.js').TypeObject}
|
|
6
|
+
*/
|
|
7
|
+
const functionType = {
|
|
8
|
+
option: ['function'],
|
|
9
|
+
stringRegex: /^function\((.*)\): (.*)$/u,
|
|
10
|
+
// Todo: Fix all the following methods up to `editUI` to work with children
|
|
11
|
+
valueMatch (x) {
|
|
12
|
+
return typeof x === 'function';
|
|
13
|
+
},
|
|
14
|
+
toValue (s) {
|
|
15
|
+
return {value: s.slice(8, -1)};
|
|
16
|
+
},
|
|
17
|
+
getInput ({root}) {
|
|
18
|
+
return /** @type {HTMLTextAreaElement} */ ($e(root, 'input'));
|
|
19
|
+
},
|
|
20
|
+
setValue ({root, value}) {
|
|
21
|
+
this.getInput({root}).value = value;
|
|
22
|
+
},
|
|
23
|
+
getValue ({root}) {
|
|
24
|
+
return this.getInput({root}).value;
|
|
25
|
+
},
|
|
26
|
+
viewUI ({value, specificSchemaObject}) {
|
|
27
|
+
return ['span', {
|
|
28
|
+
dataset: {type: 'function'},
|
|
29
|
+
title: specificSchemaObject?.description ?? '(a function)'
|
|
30
|
+
}, [value]];
|
|
31
|
+
},
|
|
32
|
+
editUI ({
|
|
33
|
+
format, type, buildTypeChoices, specificSchemaObject,
|
|
34
|
+
topRoot, // schemaContent,
|
|
35
|
+
typeNamespace
|
|
36
|
+
}) {
|
|
37
|
+
// Todo: Support `getValue`; add to demo with tests; could also add to
|
|
38
|
+
// use with `Promise` so that could also build a meaningful
|
|
39
|
+
// implementation; use schema to inform user of types of args,
|
|
40
|
+
// but remember we are not reimplementing the function schema to
|
|
41
|
+
// ask for argument types, etc.
|
|
42
|
+
|
|
43
|
+
// We want to allow overriding its descriptions
|
|
44
|
+
const specificSchemaObj = copyObject(specificSchemaObject);
|
|
45
|
+
const argsTuple = /** @type {import('zodex').SzFunction<any, any>} */ (
|
|
46
|
+
specificSchemaObj
|
|
47
|
+
)?.args ?? {type: 'tuple', items: [], rest: {type: 'any'}};
|
|
48
|
+
argsTuple.description = '';
|
|
49
|
+
// This `description` not in use, but could support
|
|
50
|
+
if (argsTuple.rest) {
|
|
51
|
+
argsTuple.rest.description = 'Argument';
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const size = argsTuple.items.length + (argsTuple.rest ? 1 : 0);
|
|
55
|
+
const args = /** @type {import('zodex').SzType} */ (
|
|
56
|
+
{
|
|
57
|
+
type: 'set',
|
|
58
|
+
minSize: size,
|
|
59
|
+
maxSize: size,
|
|
60
|
+
value: {
|
|
61
|
+
type: 'string',
|
|
62
|
+
// See https://github.com/tc39/proposal-regexp-unicode-property-escapes#other-examples
|
|
63
|
+
// eslint-disable-next-line @stylistic/max-len -- Long
|
|
64
|
+
regex: String.raw`^(?:[$_\p{ID_Start}])(?:[$_\u200C\u200D\p{ID_Continue}])*$`,
|
|
65
|
+
flags: 'v'
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
return ['div', {dataset: {type: 'function'}}, [
|
|
71
|
+
['b', ['Arguments']],
|
|
72
|
+
['br'],
|
|
73
|
+
|
|
74
|
+
// This was working to allow choice of specific function argument types,
|
|
75
|
+
// but we want function argument names to build a real function; the
|
|
76
|
+
// specific attached schema should already specify function argument
|
|
77
|
+
// types.
|
|
78
|
+
// ...(/** @type {import('../typeChoices.js').BuildTypeChoices} */ (
|
|
79
|
+
// buildTypeChoices
|
|
80
|
+
// )({
|
|
81
|
+
// // resultType,
|
|
82
|
+
// // eslint-disable-next-line object-shorthand -- TS
|
|
83
|
+
// topRoot: /** @type {HTMLDivElement} */ (topRoot),
|
|
84
|
+
// // eslint-disable-next-line object-shorthand -- TS
|
|
85
|
+
// format:
|
|
86
|
+
// /** @type {import('../formats.js').AvailableFormat} */ (format),
|
|
87
|
+
// schemaOriginal: schemaContent,
|
|
88
|
+
// schemaContent: argsTuple,
|
|
89
|
+
// state: type,
|
|
90
|
+
// // itemIndex,
|
|
91
|
+
// typeNamespace
|
|
92
|
+
// }).domArray),
|
|
93
|
+
|
|
94
|
+
...(/** @type {import('../typeChoices.js').BuildTypeChoices} */ (
|
|
95
|
+
buildTypeChoices
|
|
96
|
+
)({
|
|
97
|
+
// resultType,
|
|
98
|
+
// eslint-disable-next-line object-shorthand -- TS
|
|
99
|
+
topRoot: /** @type {HTMLDivElement} */ (topRoot),
|
|
100
|
+
// eslint-disable-next-line object-shorthand -- TS
|
|
101
|
+
format: /** @type {import('../formats.js').AvailableFormat} */ (format),
|
|
102
|
+
// schemaOriginal: schemaContent,
|
|
103
|
+
schemaContent: args,
|
|
104
|
+
state: type,
|
|
105
|
+
// itemIndex,
|
|
106
|
+
typeNamespace
|
|
107
|
+
}).domArray),
|
|
108
|
+
|
|
109
|
+
['b', ['Function body']],
|
|
110
|
+
['br'],
|
|
111
|
+
...(/** @type {import('../typeChoices.js').BuildTypeChoices} */ (
|
|
112
|
+
buildTypeChoices
|
|
113
|
+
)({
|
|
114
|
+
// resultType,
|
|
115
|
+
// eslint-disable-next-line object-shorthand -- TS
|
|
116
|
+
topRoot: /** @type {HTMLDivElement} */ (topRoot),
|
|
117
|
+
// eslint-disable-next-line object-shorthand -- TS
|
|
118
|
+
format: /** @type {import('../formats.js').AvailableFormat} */ (format),
|
|
119
|
+
// schemaOriginal: schemaContent,
|
|
120
|
+
schemaContent: {type: 'string'},
|
|
121
|
+
state: type,
|
|
122
|
+
// itemIndex,
|
|
123
|
+
typeNamespace
|
|
124
|
+
}).domArray)
|
|
125
|
+
|
|
126
|
+
// This was previously working (see commented out block above)
|
|
127
|
+
// ['b', ['Returns']],
|
|
128
|
+
// ['br'],
|
|
129
|
+
// ...(/** @type {import('../typeChoices.js').BuildTypeChoices} */ (
|
|
130
|
+
// buildTypeChoices
|
|
131
|
+
// )({
|
|
132
|
+
// // resultType,
|
|
133
|
+
// // eslint-disable-next-line object-shorthand -- TS
|
|
134
|
+
// topRoot: /** @type {HTMLDivElement} */ (topRoot),
|
|
135
|
+
// // eslint-disable-next-line object-shorthand -- TS
|
|
136
|
+
// format:
|
|
137
|
+
// /** @type {import('../formats.js').AvailableFormat} */ (format),
|
|
138
|
+
// schemaOriginal: schemaContent,
|
|
139
|
+
// schemaContent: /** @type {import('zodex').SzFunction<any, any>} */ (
|
|
140
|
+
// specificSchemaObj
|
|
141
|
+
// )?.returns ?? {type: 'any'},
|
|
142
|
+
// state: type,
|
|
143
|
+
// // itemIndex,
|
|
144
|
+
// typeNamespace
|
|
145
|
+
// }).domArray)
|
|
146
|
+
]];
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
export default functionType;
|