@knowark/componarkjs 1.14.0 → 1.14.2
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/README.md +57 -45
- package/lib/base/component/README.md +127 -0
- package/lib/base/component/component.js +127 -21
- package/lib/base/component/component.test.js +296 -3
- package/lib/base/component/index.js +3 -0
- package/lib/base/styles/index.js +4 -1
- package/lib/base/utils/define.js +2 -1
- package/lib/base/utils/format.js +12 -6
- package/lib/base/utils/helpers.js +31 -5
- package/lib/base/utils/index.js +1 -0
- package/lib/base/utils/slots.js +3 -2
- package/lib/base/utils/uuid.js +1 -1
- package/lib/components/audio/components/audio.js +17 -2
- package/lib/components/audio/index.js +1 -0
- package/lib/components/audio/styles/index.js +5 -1
- package/lib/components/camera/components/camera.js +10 -0
- package/lib/components/camera/index.js +1 -0
- package/lib/components/camera/styles/index.js +5 -1
- package/lib/components/capture/components/capture.js +18 -2
- package/lib/components/capture/index.js +1 -0
- package/lib/components/droparea/components/droparea-preview.js +58 -13
- package/lib/components/droparea/components/droparea-preview.test.js +82 -0
- package/lib/components/droparea/components/droparea.js +41 -2
- package/lib/components/droparea/index.js +1 -0
- package/lib/components/droparea/styles/index.js +5 -1
- package/lib/components/emit/components/emit.js +11 -1
- package/lib/components/emit/index.js +1 -0
- package/lib/components/index.js +2 -1
- package/lib/components/list/components/item.js +6 -0
- package/lib/components/list/components/list.js +18 -4
- package/lib/components/list/index.js +1 -0
- package/lib/components/paginator/components/paginator.js +34 -8
- package/lib/components/paginator/index.js +1 -0
- package/lib/components/paginator/styles/index.js +5 -1
- package/lib/components/spinner/components/spinner.js +10 -0
- package/lib/components/spinner/index.js +1 -0
- package/lib/components/spinner/styles/index.js +5 -1
- package/lib/components/splitview/components/splitview.detail.js +10 -1
- package/lib/components/splitview/components/splitview.js +18 -3
- package/lib/components/splitview/components/splitview.master.js +10 -0
- package/lib/components/splitview/index.js +1 -0
- package/lib/components/translate/components/translate.js +42 -11
- package/lib/components/translate/components/translate.test.js +169 -1
- package/lib/components/translate/index.js +1 -0
- package/lib/index.js +3 -0
- package/package.json +2 -1
- package/tsconfig.json +1 -1
- package/types/base/component/component.d.ts +43 -8
- package/types/base/component/component.d.ts.map +1 -1
- package/types/base/component/index.d.ts +4 -6
- package/types/base/component/index.d.ts.map +1 -1
- package/types/base/styles/index.d.ts +3 -2
- package/types/base/styles/index.d.ts.map +1 -1
- package/types/base/utils/define.d.ts +3 -2
- package/types/base/utils/define.d.ts.map +1 -1
- package/types/base/utils/format.d.ts +12 -6
- package/types/base/utils/format.d.ts.map +1 -1
- package/types/base/utils/helpers.d.ts +27 -7
- package/types/base/utils/helpers.d.ts.map +1 -1
- package/types/base/utils/slots.d.ts +8 -10
- package/types/base/utils/slots.d.ts.map +1 -1
- package/types/base/utils/uuid.d.ts +1 -1
- package/types/base/utils/uuid.d.ts.map +1 -1
- package/types/components/audio/components/audio.d.ts +23 -9
- package/types/components/audio/components/audio.d.ts.map +1 -1
- package/types/components/audio/styles/index.d.ts +3 -2
- package/types/components/audio/styles/index.d.ts.map +1 -1
- package/types/components/camera/components/camera.d.ts +11 -3
- package/types/components/camera/components/camera.d.ts.map +1 -1
- package/types/components/camera/styles/index.d.ts +3 -2
- package/types/components/camera/styles/index.d.ts.map +1 -1
- package/types/components/capture/components/capture.d.ts +23 -3
- package/types/components/capture/components/capture.d.ts.map +1 -1
- package/types/components/droparea/components/droparea-preview.d.ts +64 -11
- package/types/components/droparea/components/droparea-preview.d.ts.map +1 -1
- package/types/components/droparea/components/droparea.d.ts +58 -13
- package/types/components/droparea/components/droparea.d.ts.map +1 -1
- package/types/components/droparea/styles/index.d.ts +3 -2
- package/types/components/droparea/styles/index.d.ts.map +1 -1
- package/types/components/emit/components/emit.d.ts +15 -3
- package/types/components/emit/components/emit.d.ts.map +1 -1
- package/types/components/list/components/item.d.ts +8 -1
- package/types/components/list/components/item.d.ts.map +1 -1
- package/types/components/list/components/list.d.ts +23 -5
- package/types/components/list/components/list.d.ts.map +1 -1
- package/types/components/paginator/components/paginator.d.ts +32 -8
- package/types/components/paginator/components/paginator.d.ts.map +1 -1
- package/types/components/paginator/styles/index.d.ts +3 -2
- package/types/components/paginator/styles/index.d.ts.map +1 -1
- package/types/components/spinner/components/spinner.d.ts +14 -3
- package/types/components/spinner/components/spinner.d.ts.map +1 -1
- package/types/components/spinner/styles/index.d.ts +3 -2
- package/types/components/spinner/styles/index.d.ts.map +1 -1
- package/types/components/splitview/components/splitview.d.ts +22 -4
- package/types/components/splitview/components/splitview.d.ts.map +1 -1
- package/types/components/splitview/components/splitview.detail.d.ts +12 -2
- package/types/components/splitview/components/splitview.detail.d.ts.map +1 -1
- package/types/components/splitview/components/splitview.master.d.ts +12 -1
- package/types/components/splitview/components/splitview.master.d.ts.map +1 -1
- package/types/components/translate/components/translate.d.ts +44 -10
- package/types/components/translate/components/translate.d.ts.map +1 -1
- package/lib/base/component/README.rst +0 -113
|
@@ -64,6 +64,44 @@ class PlainLoadComponent extends Component {
|
|
|
64
64
|
}
|
|
65
65
|
Component.define('plain-load-component', PlainLoadComponent)
|
|
66
66
|
|
|
67
|
+
class StringLoadComponent extends Component {
|
|
68
|
+
load () {
|
|
69
|
+
throw 'String Load Error!'
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
Component.define('string-load-component', StringLoadComponent)
|
|
73
|
+
|
|
74
|
+
class CleanupComponent extends Component {
|
|
75
|
+
init (context = {}) {
|
|
76
|
+
this.cleanupCalls = 0
|
|
77
|
+
return super.init(context)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
render () {
|
|
81
|
+
return super.render()
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
Component.define('cleanup-component', CleanupComponent)
|
|
85
|
+
|
|
86
|
+
class OptimizedListenerComponent extends Component {
|
|
87
|
+
init (context = {}) {
|
|
88
|
+
this.clicks = 0
|
|
89
|
+
return super.init(context)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
render () {
|
|
93
|
+
if (!this.querySelector('button')) {
|
|
94
|
+
this.content = '<button listen on-click="onClick">Click me</button>'
|
|
95
|
+
}
|
|
96
|
+
return super.render()
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
onClick () {
|
|
100
|
+
this.clicks += 1
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
Component.define('optimized-listener-component', OptimizedListenerComponent)
|
|
104
|
+
|
|
67
105
|
let container = null
|
|
68
106
|
let component = null
|
|
69
107
|
|
|
@@ -166,6 +204,10 @@ it('catches and re-raises connectedCallback errors', async () => {
|
|
|
166
204
|
const component = /** @type {Component} */ (
|
|
167
205
|
document.createElement('mock-component'))
|
|
168
206
|
const consoleErrorMock = mock.method(console, 'error', () => {})
|
|
207
|
+
let errorEvent = null
|
|
208
|
+
component.addEventListener('error', (event) => {
|
|
209
|
+
errorEvent = event
|
|
210
|
+
})
|
|
169
211
|
component.render = () => {
|
|
170
212
|
throw new Error('Render Error!')
|
|
171
213
|
}
|
|
@@ -174,14 +216,72 @@ it('catches and re-raises connectedCallback errors', async () => {
|
|
|
174
216
|
component.connectedCallback()
|
|
175
217
|
} catch (error) {
|
|
176
218
|
assert.deepStrictEqual(error.message, 'Render Error!')
|
|
219
|
+
assert.deepStrictEqual(errorEvent.detail.phase, 'init-render')
|
|
220
|
+
assert.deepStrictEqual(errorEvent.detail.component, 'MOCK-COMPONENT')
|
|
177
221
|
} finally {
|
|
178
222
|
consoleErrorMock.mock.restore()
|
|
179
223
|
}
|
|
180
224
|
})
|
|
181
225
|
|
|
182
|
-
it('
|
|
183
|
-
|
|
184
|
-
|
|
226
|
+
it('creates events without CustomEvent and keeps event details', () => {
|
|
227
|
+
setup()
|
|
228
|
+
const component = container.querySelector('mock-component')
|
|
229
|
+
const previousCustomEvent = globalThis.CustomEvent
|
|
230
|
+
|
|
231
|
+
try {
|
|
232
|
+
globalThis.CustomEvent = undefined
|
|
233
|
+
let detail = null
|
|
234
|
+
component.addEventListener('fallback-emit', (event) => {
|
|
235
|
+
detail = event.detail
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
component.emit('fallback-emit', { ready: true })
|
|
239
|
+
|
|
240
|
+
assert.deepStrictEqual(detail, { ready: true })
|
|
241
|
+
} finally {
|
|
242
|
+
globalThis.CustomEvent = previousCustomEvent
|
|
243
|
+
}
|
|
244
|
+
})
|
|
245
|
+
|
|
246
|
+
it('creates events from the component global window Event fallback', () => {
|
|
247
|
+
setup()
|
|
248
|
+
const component = document.createElement('mock-component')
|
|
249
|
+
const previousGlobal = component.global
|
|
250
|
+
|
|
251
|
+
try {
|
|
252
|
+
component.global = {
|
|
253
|
+
document: {
|
|
254
|
+
defaultView: {
|
|
255
|
+
Event: globalThis.Event
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const event = component._createEvent('context-window-event', { ready: true })
|
|
261
|
+
|
|
262
|
+
assert.deepStrictEqual(event.type, 'context-window-event')
|
|
263
|
+
assert.deepStrictEqual(event.detail.ready, true)
|
|
264
|
+
assert.deepStrictEqual(typeof event.stopPropagation, 'function')
|
|
265
|
+
} finally {
|
|
266
|
+
component.global = previousGlobal
|
|
267
|
+
}
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
it('creates events from globalThis CustomEvent when component global has no window objects', () => {
|
|
271
|
+
setup()
|
|
272
|
+
const component = document.createElement('mock-component')
|
|
273
|
+
|
|
274
|
+
component.global = {}
|
|
275
|
+
const event = component._createEvent('global-custom-event', { ready: true })
|
|
276
|
+
|
|
277
|
+
assert.deepStrictEqual(event.type, 'global-custom-event')
|
|
278
|
+
assert.deepStrictEqual(event.detail.ready, true)
|
|
279
|
+
assert.deepStrictEqual(event instanceof globalThis.CustomEvent, true)
|
|
280
|
+
})
|
|
281
|
+
|
|
282
|
+
it('emits an error event when async load fails', async () => {
|
|
283
|
+
setup()
|
|
284
|
+
const component = document.createElement('async-load-component')
|
|
185
285
|
let errorEvent = null
|
|
186
286
|
|
|
187
287
|
component.addEventListener('error', (event) => {
|
|
@@ -194,6 +294,8 @@ it('emits an error event when async load fails', async () => {
|
|
|
194
294
|
|
|
195
295
|
assert.ok(errorEvent)
|
|
196
296
|
assert.deepStrictEqual(errorEvent.detail.message, 'Async Load Error!')
|
|
297
|
+
assert.deepStrictEqual(errorEvent.detail.phase, 'load')
|
|
298
|
+
assert.deepStrictEqual(errorEvent.detail.component, 'ASYNC-LOAD-COMPONENT')
|
|
197
299
|
})
|
|
198
300
|
|
|
199
301
|
it('emits an error event and throws when sync load fails', () => {
|
|
@@ -211,6 +313,176 @@ it('emits an error event and throws when sync load fails', () => {
|
|
|
211
313
|
|
|
212
314
|
assert.ok(errorEvent)
|
|
213
315
|
assert.deepStrictEqual(errorEvent.detail.message, 'Sync Load Error!')
|
|
316
|
+
assert.deepStrictEqual(errorEvent.detail.phase, 'load')
|
|
317
|
+
assert.deepStrictEqual(errorEvent.detail.component, 'SYNC-LOAD-COMPONENT')
|
|
318
|
+
})
|
|
319
|
+
|
|
320
|
+
it('coerces non-error load failures into errors with metadata', () => {
|
|
321
|
+
setup()
|
|
322
|
+
const component = document.createElement('string-load-component')
|
|
323
|
+
let errorEvent = null
|
|
324
|
+
|
|
325
|
+
component.addEventListener('error', (event) => {
|
|
326
|
+
errorEvent = event
|
|
327
|
+
})
|
|
328
|
+
|
|
329
|
+
assert.throws(() => {
|
|
330
|
+
component.connectedCallback()
|
|
331
|
+
}, /String Load Error!/)
|
|
332
|
+
|
|
333
|
+
assert.ok(errorEvent)
|
|
334
|
+
assert.deepStrictEqual(errorEvent.detail.message, 'String Load Error!')
|
|
335
|
+
assert.deepStrictEqual(errorEvent.detail.phase, 'load')
|
|
336
|
+
assert.deepStrictEqual(errorEvent.detail.component, 'STRING-LOAD-COMPONENT')
|
|
337
|
+
})
|
|
338
|
+
|
|
339
|
+
it('creates resolve events without CustomEvent and still resolves', () => {
|
|
340
|
+
setup()
|
|
341
|
+
const component = document.createElement('mock-component')
|
|
342
|
+
const previousCustomEvent = globalThis.CustomEvent
|
|
343
|
+
|
|
344
|
+
try {
|
|
345
|
+
globalThis.CustomEvent = undefined
|
|
346
|
+
let resource = null
|
|
347
|
+
component.addEventListener('resolve', (event) => {
|
|
348
|
+
resource = event.detail.resource
|
|
349
|
+
})
|
|
350
|
+
|
|
351
|
+
const result = component.resolve('dependency')
|
|
352
|
+
|
|
353
|
+
assert.deepStrictEqual(resource, 'dependency')
|
|
354
|
+
assert.strictEqual(result, undefined)
|
|
355
|
+
} finally {
|
|
356
|
+
globalThis.CustomEvent = previousCustomEvent
|
|
357
|
+
}
|
|
358
|
+
})
|
|
359
|
+
|
|
360
|
+
it('creates fallback events when neither CustomEvent nor Event are available', () => {
|
|
361
|
+
setup()
|
|
362
|
+
const component = document.createElement('mock-component')
|
|
363
|
+
const previousCustomEvent = globalThis.CustomEvent
|
|
364
|
+
const previousEvent = globalThis.Event
|
|
365
|
+
|
|
366
|
+
try {
|
|
367
|
+
globalThis.CustomEvent = undefined
|
|
368
|
+
globalThis.Event = undefined
|
|
369
|
+
|
|
370
|
+
component.global = {}
|
|
371
|
+
const event = component._createEvent('fallback', { ready: true })
|
|
372
|
+
|
|
373
|
+
assert.deepStrictEqual(event.type, 'fallback')
|
|
374
|
+
assert.deepStrictEqual(event.detail, { ready: true })
|
|
375
|
+
assert.deepStrictEqual(typeof event.stopPropagation, 'function')
|
|
376
|
+
assert.deepStrictEqual(typeof event.preventDefault, 'function')
|
|
377
|
+
assert.doesNotThrow(() => event.stopPropagation())
|
|
378
|
+
assert.doesNotThrow(() => event.preventDefault())
|
|
379
|
+
} finally {
|
|
380
|
+
globalThis.CustomEvent = previousCustomEvent
|
|
381
|
+
globalThis.Event = previousEvent
|
|
382
|
+
}
|
|
383
|
+
})
|
|
384
|
+
|
|
385
|
+
it('falls back to globalThis when component global is missing', () => {
|
|
386
|
+
setup()
|
|
387
|
+
const component = document.createElement('mock-component')
|
|
388
|
+
const previousCustomEvent = globalThis.CustomEvent
|
|
389
|
+
|
|
390
|
+
try {
|
|
391
|
+
globalThis.CustomEvent = undefined
|
|
392
|
+
component.global = null
|
|
393
|
+
|
|
394
|
+
const event = component._createEvent('global-fallback', { ready: true })
|
|
395
|
+
|
|
396
|
+
assert.deepStrictEqual(event.type, 'global-fallback')
|
|
397
|
+
assert.deepStrictEqual(event.detail.ready, true)
|
|
398
|
+
} finally {
|
|
399
|
+
globalThis.CustomEvent = previousCustomEvent
|
|
400
|
+
}
|
|
401
|
+
})
|
|
402
|
+
|
|
403
|
+
it('registers and runs cleanup callbacks on disconnect', () => {
|
|
404
|
+
setup()
|
|
405
|
+
const component = document.createElement('cleanup-component')
|
|
406
|
+
container.appendChild(component)
|
|
407
|
+
|
|
408
|
+
let cleanupCalls = 0
|
|
409
|
+
component.registerCleanup(() => {
|
|
410
|
+
cleanupCalls += 1
|
|
411
|
+
})
|
|
412
|
+
component.registerCleanup(() => {
|
|
413
|
+
cleanupCalls += 1
|
|
414
|
+
})
|
|
415
|
+
|
|
416
|
+
component.disconnectedCallback()
|
|
417
|
+
|
|
418
|
+
assert.deepStrictEqual(cleanupCalls, 2)
|
|
419
|
+
})
|
|
420
|
+
|
|
421
|
+
it('supports unregistering cleanup callbacks', () => {
|
|
422
|
+
setup()
|
|
423
|
+
const component = document.createElement('cleanup-component')
|
|
424
|
+
container.appendChild(component)
|
|
425
|
+
|
|
426
|
+
let cleanupCalls = 0
|
|
427
|
+
const unregister = component.registerCleanup(() => {
|
|
428
|
+
cleanupCalls += 1
|
|
429
|
+
})
|
|
430
|
+
unregister()
|
|
431
|
+
unregister()
|
|
432
|
+
|
|
433
|
+
component.disconnectedCallback()
|
|
434
|
+
|
|
435
|
+
assert.deepStrictEqual(cleanupCalls, 0)
|
|
436
|
+
})
|
|
437
|
+
|
|
438
|
+
it('supports disconnected init fast-path when local state is already set', () => {
|
|
439
|
+
setup()
|
|
440
|
+
const component = document.createElement('mock-component')
|
|
441
|
+
component.local = { preset: true }
|
|
442
|
+
const initSpy = mock.method(component, 'init')
|
|
443
|
+
container.appendChild(component)
|
|
444
|
+
|
|
445
|
+
assert.deepStrictEqual(initSpy.mock.calls.length, 0)
|
|
446
|
+
initSpy.mock.restore()
|
|
447
|
+
})
|
|
448
|
+
|
|
449
|
+
it('returns unchanged values when enhanced error details are absent', () => {
|
|
450
|
+
setup()
|
|
451
|
+
const component = document.createElement('cleanup-component')
|
|
452
|
+
|
|
453
|
+
const result = component._enhanceError(undefined, 'init-render')
|
|
454
|
+
|
|
455
|
+
assert.strictEqual(result, undefined)
|
|
456
|
+
})
|
|
457
|
+
|
|
458
|
+
it('accepts non-function cleanup callbacks as no-op registrations', () => {
|
|
459
|
+
setup()
|
|
460
|
+
const component = document.createElement('cleanup-component')
|
|
461
|
+
|
|
462
|
+
const unregister = component.registerCleanup()
|
|
463
|
+
|
|
464
|
+
assert.doesNotThrow(() => unregister())
|
|
465
|
+
})
|
|
466
|
+
|
|
467
|
+
it('emits an error event when a cleanup callback throws', () => {
|
|
468
|
+
setup()
|
|
469
|
+
const component = document.createElement('cleanup-component')
|
|
470
|
+
container.appendChild(component)
|
|
471
|
+
let errorEvent = null
|
|
472
|
+
|
|
473
|
+
component.addEventListener('error', (event) => {
|
|
474
|
+
errorEvent = event
|
|
475
|
+
})
|
|
476
|
+
component.registerCleanup(() => {
|
|
477
|
+
throw new Error('Cleanup failed')
|
|
478
|
+
})
|
|
479
|
+
|
|
480
|
+
component.disconnectedCallback()
|
|
481
|
+
|
|
482
|
+
assert.ok(errorEvent)
|
|
483
|
+
assert.deepStrictEqual(errorEvent.detail.message, 'Cleanup failed')
|
|
484
|
+
assert.deepStrictEqual(errorEvent.detail.phase, 'cleanup')
|
|
485
|
+
assert.deepStrictEqual(errorEvent.detail.component, 'CLEANUP-COMPONENT')
|
|
214
486
|
})
|
|
215
487
|
|
|
216
488
|
it('supports load implementations that do not return promises', () => {
|
|
@@ -611,3 +883,24 @@ it('provides a styleNames utility function for setting styles', () => {
|
|
|
611
883
|
|
|
612
884
|
assert.deepStrictEqual(result, 'background-primary shadow-small')
|
|
613
885
|
})
|
|
886
|
+
|
|
887
|
+
it('reuses listener bindings when content does not change', () => {
|
|
888
|
+
setup()
|
|
889
|
+
container.innerHTML = `
|
|
890
|
+
<optimized-listener-component></optimized-listener-component>
|
|
891
|
+
`
|
|
892
|
+
const component = container.querySelector('optimized-listener-component')
|
|
893
|
+
|
|
894
|
+
component.render()
|
|
895
|
+
component.querySelector('button').click()
|
|
896
|
+
|
|
897
|
+
component.render()
|
|
898
|
+
component.querySelector('button').click()
|
|
899
|
+
|
|
900
|
+
component.content = '<button listen on-click="onClick">Click me</button>'
|
|
901
|
+
component.render()
|
|
902
|
+
component.querySelector('button').click()
|
|
903
|
+
|
|
904
|
+
assert.deepStrictEqual(component.clicks, 3)
|
|
905
|
+
assert.deepStrictEqual(component._needsBinding, false)
|
|
906
|
+
})
|
package/lib/base/styles/index.js
CHANGED
package/lib/base/utils/define.js
CHANGED
|
@@ -5,7 +5,8 @@ const fallbackRegistry = new Map()
|
|
|
5
5
|
|
|
6
6
|
/** @param {string} tag
|
|
7
7
|
* @param {CustomElementConstructor} element
|
|
8
|
-
* @param {string} styles
|
|
8
|
+
* @param {string} [styles]
|
|
9
|
+
* @returns {CSSStyleSheet|HTMLStyleElement|undefined} */
|
|
9
10
|
export function define (tag, element, styles = '') {
|
|
10
11
|
const definedElement = globalThis.customElements.get(tag)
|
|
11
12
|
if (!definedElement) {
|
package/lib/base/utils/format.js
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Convert Strings from camelCase to kebab-case
|
|
3
|
-
* @param {string} input
|
|
2
|
+
* Convert Strings from camelCase to kebab-case.
|
|
3
|
+
* @param {string} input
|
|
4
|
+
* @returns {string}
|
|
5
|
+
*/
|
|
4
6
|
export function camelToKebab (input) {
|
|
5
7
|
return input.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase()
|
|
6
8
|
}
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
|
-
* Convert Strings from kebab-case to camelCase
|
|
10
|
-
* @param {string} input
|
|
11
|
+
* Convert Strings from kebab-case to camelCase.
|
|
12
|
+
* @param {string} input
|
|
13
|
+
* @returns {string}
|
|
14
|
+
*/
|
|
11
15
|
export function kebabToCamel (input) {
|
|
12
16
|
return input.replace(/-([a-z])/g, function (g) {
|
|
13
17
|
return g[1].toUpperCase()
|
|
@@ -15,8 +19,10 @@ export function kebabToCamel (input) {
|
|
|
15
19
|
}
|
|
16
20
|
|
|
17
21
|
/**
|
|
18
|
-
* Convert Strings from snake to camelCase
|
|
19
|
-
* @param {string} input
|
|
22
|
+
* Convert Strings from snake to camelCase.
|
|
23
|
+
* @param {string} input
|
|
24
|
+
* @returns {string}
|
|
25
|
+
*/
|
|
20
26
|
export function snakeToCamel (input) {
|
|
21
27
|
return input.replace(/_([a-z])/g, function (g) {
|
|
22
28
|
return g[1].toUpperCase()
|
|
@@ -1,6 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @import { Component } from '../component/component.js'
|
|
3
|
+
*/
|
|
1
4
|
import { camelToKebab } from './format.js'
|
|
2
5
|
|
|
3
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* Binds declarative event handlers in descendant nodes for a component.
|
|
8
|
+
* @param {Component|HTMLElement} self
|
|
9
|
+
* @returns {void}
|
|
10
|
+
*/
|
|
4
11
|
export function listen (self) {
|
|
5
12
|
/** @ts-ignore */
|
|
6
13
|
const binding = self.binding
|
|
@@ -62,7 +69,11 @@ export function listen (self) {
|
|
|
62
69
|
}
|
|
63
70
|
}
|
|
64
71
|
|
|
65
|
-
/**
|
|
72
|
+
/**
|
|
73
|
+
* Resolve dependencies from descendants using `resolve` events.
|
|
74
|
+
* @param {Component|HTMLElement} self
|
|
75
|
+
* @returns {void}
|
|
76
|
+
*/
|
|
66
77
|
function provide (self) {
|
|
67
78
|
/** @ts-ignore */
|
|
68
79
|
if (!self.provide) return
|
|
@@ -102,7 +113,13 @@ function transform (pipe, value) {
|
|
|
102
113
|
}[pipe?.toLowerCase() || 'string'](value)
|
|
103
114
|
}
|
|
104
115
|
|
|
105
|
-
/**
|
|
116
|
+
/**
|
|
117
|
+
* Sets a nested property value by object path.
|
|
118
|
+
* @param {unknown} object
|
|
119
|
+
* @param {string} path
|
|
120
|
+
* @param {any} value
|
|
121
|
+
* @returns {void}
|
|
122
|
+
*/
|
|
106
123
|
export function set (object, path, value) {
|
|
107
124
|
const pathArray = path.match(/([^[.\]])+/g)
|
|
108
125
|
if (!pathArray?.length) return
|
|
@@ -114,7 +131,13 @@ export function set (object, path, value) {
|
|
|
114
131
|
}, object)
|
|
115
132
|
}
|
|
116
133
|
|
|
117
|
-
/**
|
|
134
|
+
/**
|
|
135
|
+
* Reads a nested property value by path.
|
|
136
|
+
* @param {unknown} object
|
|
137
|
+
* @param {string} path
|
|
138
|
+
* @param {any} fallback
|
|
139
|
+
* @returns {any}
|
|
140
|
+
*/
|
|
118
141
|
export function get (object, path, fallback) {
|
|
119
142
|
const pathArray = path.match(/([^[.\]])+/g)
|
|
120
143
|
if (!pathArray?.length) return fallback
|
|
@@ -125,7 +148,10 @@ export function get (object, path, fallback) {
|
|
|
125
148
|
return value === undefined ? fallback : value
|
|
126
149
|
}
|
|
127
150
|
|
|
128
|
-
/** @param {object} object
|
|
151
|
+
/** @param {object} object
|
|
152
|
+
* @return {string}
|
|
153
|
+
* @description Returns truthy CSS class names from object values.
|
|
154
|
+
*/
|
|
129
155
|
export function keys (object) {
|
|
130
156
|
return Object.keys(object).filter(
|
|
131
157
|
key => Boolean(object[key])).join(' ')
|
package/lib/base/utils/index.js
CHANGED
package/lib/base/utils/slots.js
CHANGED
package/lib/base/utils/uuid.js
CHANGED
|
@@ -2,8 +2,16 @@ import { Component } from '#base/index.js'
|
|
|
2
2
|
import styles from '../styles/index.js'
|
|
3
3
|
|
|
4
4
|
const tag = 'ark-audio'
|
|
5
|
+
/**
|
|
6
|
+
* Audio recorder component.
|
|
7
|
+
* Emits:
|
|
8
|
+
* - `error` with `Error` detail on capture/rendering issues.
|
|
9
|
+
*/
|
|
5
10
|
export class Audio extends Component {
|
|
11
|
+
/** @param {object} context
|
|
12
|
+
* @returns {this} */
|
|
6
13
|
init (context = {}) {
|
|
14
|
+
/** @type {'idle'|'recording'|'done'} */
|
|
7
15
|
this.status = 'idle'
|
|
8
16
|
this.dataURL = null
|
|
9
17
|
this.timerId = null
|
|
@@ -18,6 +26,7 @@ export class Audio extends Component {
|
|
|
18
26
|
return ['status']
|
|
19
27
|
}
|
|
20
28
|
|
|
29
|
+
/** @returns {this} */
|
|
21
30
|
render () {
|
|
22
31
|
if (this.status === 'done') {
|
|
23
32
|
this.content = `
|
|
@@ -45,7 +54,8 @@ export class Audio extends Component {
|
|
|
45
54
|
return super.render()
|
|
46
55
|
}
|
|
47
56
|
|
|
48
|
-
/** @param {Event} event
|
|
57
|
+
/** @param {Event} event
|
|
58
|
+
* @returns {Promise<void>} */
|
|
49
59
|
async start (event) {
|
|
50
60
|
event.stopPropagation()
|
|
51
61
|
this.status = 'recording'
|
|
@@ -60,7 +70,8 @@ export class Audio extends Component {
|
|
|
60
70
|
this.recorder.start()
|
|
61
71
|
}
|
|
62
72
|
|
|
63
|
-
/** @param {Event} event
|
|
73
|
+
/** @param {Event} event
|
|
74
|
+
* @returns {void} */
|
|
64
75
|
stop (event) {
|
|
65
76
|
event.stopPropagation()
|
|
66
77
|
this.status = 'done'
|
|
@@ -70,6 +81,7 @@ export class Audio extends Component {
|
|
|
70
81
|
this.render()
|
|
71
82
|
}
|
|
72
83
|
|
|
84
|
+
/** @returns {void} */
|
|
73
85
|
reset () {
|
|
74
86
|
clearInterval(this.timerId)
|
|
75
87
|
this._revokeObjectURL()
|
|
@@ -80,6 +92,7 @@ export class Audio extends Component {
|
|
|
80
92
|
this.recorder = null
|
|
81
93
|
}
|
|
82
94
|
|
|
95
|
+
/** @returns {void} */
|
|
83
96
|
disconnectedCallback () {
|
|
84
97
|
clearInterval(this.timerId)
|
|
85
98
|
this.recorder?.stream?.getTracks?.().forEach(track => track.stop())
|
|
@@ -87,6 +100,7 @@ export class Audio extends Component {
|
|
|
87
100
|
super.disconnectedCallback()
|
|
88
101
|
}
|
|
89
102
|
|
|
103
|
+
/** @returns {ReturnType<typeof setInterval>} Interval handle. */
|
|
90
104
|
_time () {
|
|
91
105
|
let count = 0
|
|
92
106
|
return setInterval(() => {
|
|
@@ -113,6 +127,7 @@ export class Audio extends Component {
|
|
|
113
127
|
reader.onloadend = () => { this.dataURL = reader.result }
|
|
114
128
|
}
|
|
115
129
|
|
|
130
|
+
/** @returns {void} */
|
|
116
131
|
_revokeObjectURL () {
|
|
117
132
|
if (!this.objectURL) return
|
|
118
133
|
this.global.URL.revokeObjectURL?.(this.objectURL)
|
|
@@ -2,7 +2,12 @@ import { Component } from '#base/index.js'
|
|
|
2
2
|
import styles from '../styles/index.js'
|
|
3
3
|
|
|
4
4
|
const tag = 'ark-camera'
|
|
5
|
+
/**
|
|
6
|
+
* Camera capture component.
|
|
7
|
+
*/
|
|
5
8
|
export class Camera extends Component {
|
|
9
|
+
/** @param {object} context
|
|
10
|
+
* @returns {this} */
|
|
6
11
|
init (context = {}) {
|
|
7
12
|
this.width = this.width || context.width || 320
|
|
8
13
|
this.height = this.height || context.height || 320
|
|
@@ -47,6 +52,7 @@ export class Camera extends Component {
|
|
|
47
52
|
return canvas.toDataURL('image/jpg')
|
|
48
53
|
}
|
|
49
54
|
|
|
55
|
+
/** @returns {Promise<void>} */
|
|
50
56
|
async start () {
|
|
51
57
|
const stream = await this.global.navigator.mediaDevices.getUserMedia({
|
|
52
58
|
video: {
|
|
@@ -60,18 +66,22 @@ export class Camera extends Component {
|
|
|
60
66
|
this.video.srcObject = stream
|
|
61
67
|
}
|
|
62
68
|
|
|
69
|
+
/** @returns {void} */
|
|
63
70
|
stop () {
|
|
64
71
|
// @ts-ignore
|
|
65
72
|
const tracks = this.video.srcObject ? this.video.srcObject.getTracks() : []
|
|
66
73
|
tracks.forEach(track => track.stop())
|
|
67
74
|
}
|
|
68
75
|
|
|
76
|
+
/** @param {string} facingMode
|
|
77
|
+
* @returns {Promise<void>} */
|
|
69
78
|
async setCameraOrientation (facingMode) {
|
|
70
79
|
this.stop()
|
|
71
80
|
this.facingMode = facingMode
|
|
72
81
|
await this.start()
|
|
73
82
|
}
|
|
74
83
|
|
|
84
|
+
/** @returns {void} */
|
|
75
85
|
disconnectedCallback () {
|
|
76
86
|
this.stop()
|
|
77
87
|
super.disconnectedCallback()
|