@camera.ui/sdk 0.0.3 → 0.0.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/LICENSE.md +1 -1
- package/README.md +2 -2
- package/dist/camera/events.js +2 -0
- package/dist/camera/index.js +3 -1
- package/dist/external.js +7 -0
- package/dist/index.d.ts +7132 -4248
- package/dist/index.js +3 -11
- package/dist/internal/contract-validators.js +21 -0
- package/dist/internal/index.d.ts +915 -0
- package/dist/internal/index.js +9 -0
- package/dist/internal/sensor-triggers.js +2 -0
- package/dist/internal/shared-utils.js +86 -0
- package/dist/internal/streaming-internal.js +1 -0
- package/dist/manager/index.js +1 -1
- package/dist/observable/index.js +419 -0
- package/dist/plugin/api.js +21 -0
- package/dist/plugin/contract.js +101 -114
- package/dist/plugin/helper.js +277 -0
- package/dist/plugin/index.js +4 -1
- package/dist/plugin/interfaces.js +51 -1
- package/dist/plugin/notifier.js +23 -0
- package/dist/plugin/oauth.js +1 -0
- package/dist/sensor/audio.js +103 -81
- package/dist/sensor/base.js +350 -318
- package/dist/sensor/battery.js +73 -59
- package/dist/sensor/classifier.js +117 -0
- package/dist/sensor/clip.js +30 -0
- package/dist/sensor/contact.js +37 -18
- package/dist/sensor/detection.js +4 -0
- package/dist/sensor/doorbell.js +52 -38
- package/dist/sensor/face.js +71 -86
- package/dist/sensor/garage.js +121 -0
- package/dist/sensor/humidity.js +52 -0
- package/dist/sensor/index.js +17 -11
- package/dist/sensor/leak.js +52 -0
- package/dist/sensor/licensePlate.js +70 -79
- package/dist/sensor/light.js +82 -38
- package/dist/sensor/lock.js +99 -0
- package/dist/sensor/motion.js +85 -70
- package/dist/sensor/object.js +73 -94
- package/dist/sensor/occupancy.js +52 -0
- package/dist/sensor/ptz.js +114 -100
- package/dist/sensor/securitySystem.js +98 -0
- package/dist/sensor/siren.js +75 -43
- package/dist/sensor/smoke.js +52 -0
- package/dist/sensor/spec.js +1 -0
- package/dist/sensor/switch.js +72 -0
- package/dist/sensor/temperature.js +52 -0
- package/dist/storage/index.js +1 -2
- package/dist/types.js +1 -0
- package/docs/.vitepress/config.ts +77 -0
- package/docs/.vitepress/theme/index.ts +5 -0
- package/docs/.vitepress/theme/style.css +117 -0
- package/docs/index.md +16 -0
- package/docs/logo.png +0 -0
- package/docs/public/apple-touch-icon.png +0 -0
- package/docs/public/favicon-16.ico +0 -0
- package/docs/public/favicon.ico +0 -0
- package/docs/public/logo.svg +1 -0
- package/examples/README.md +7 -0
- package/examples/getting-started.md +535 -0
- package/package.json +36 -23
- package/scripts/build-example-docs.mjs +62 -0
- package/tsconfig.node.json +3 -2
- package/typedoc.json +42 -0
- package/dist/sensor/guards.js +0 -133
- package/dist/sensor/types.js +0 -46
- package/dist/service/base.js +0 -96
- package/dist/service/index.js +0 -3
- /package/dist/camera/{types.js → enums.js} +0 -0
- /package/dist/{manager/types.js → camera/frames.js} +0 -0
- /package/dist/{plugin/types.js → internal/camera-config-internal.js} +0 -0
- /package/dist/{service/services.js → internal/camera-enums.js} +0 -0
- /package/dist/{service/types.js → internal/camera-wire.js} +0 -0
- /package/dist/{storage/schema.js → internal/manager-rpc.js} +0 -0
- /package/dist/{storage/storages.js → internal/sensor-rpc.js} +0 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { Sensor, SensorType, SensorCategory } from './base.js';
|
|
2
|
+
/**
|
|
3
|
+
* Properties for switch controls
|
|
4
|
+
*
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
7
|
+
export var SwitchProperty;
|
|
8
|
+
(function (SwitchProperty) {
|
|
9
|
+
/** Whether the switch is on */
|
|
10
|
+
SwitchProperty["On"] = "on";
|
|
11
|
+
})(SwitchProperty || (SwitchProperty = {}));
|
|
12
|
+
/**
|
|
13
|
+
* Generic on/off switch control. Override `setOn()` / `setOff()` to drive
|
|
14
|
+
* hardware and call `await super.setOn()` / `await super.setOff()` after
|
|
15
|
+
* success to sync the SDK state. For hardware-pushed updates, call the `super`
|
|
16
|
+
* methods from your event handler.
|
|
17
|
+
*/
|
|
18
|
+
export class SwitchControl extends Sensor {
|
|
19
|
+
type = SensorType.Switch;
|
|
20
|
+
category = SensorCategory.Control;
|
|
21
|
+
constructor(name = 'Switch') {
|
|
22
|
+
super(name);
|
|
23
|
+
this._writeState({ [SwitchProperty.On]: false });
|
|
24
|
+
}
|
|
25
|
+
get on() {
|
|
26
|
+
return this.props.on;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Turn the switch on. Override to drive hardware and call `await super.setOn()`
|
|
30
|
+
* after success to sync the SDK state.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* await sw.setOn();
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
async setOn() {
|
|
38
|
+
this._writeState({ [SwitchProperty.On]: true });
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Turn the switch off. Override to drive hardware and call `await super.setOff()`
|
|
42
|
+
* after success to sync the SDK state.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* await sw.setOff();
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
async setOff() {
|
|
50
|
+
this._writeState({ [SwitchProperty.On]: false });
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Cross-process consumer entry point. Dispatches writable properties
|
|
54
|
+
* to semantic methods so plugin overrides (hardware actions) are honored.
|
|
55
|
+
* Unknown properties are ignored — only `On` is externally writable.
|
|
56
|
+
*
|
|
57
|
+
* @param property - Property name to write.
|
|
58
|
+
*
|
|
59
|
+
* @param value - New value for the property.
|
|
60
|
+
*
|
|
61
|
+
* @internal
|
|
62
|
+
*/
|
|
63
|
+
async updateValue(property, value) {
|
|
64
|
+
if (property === SwitchProperty.On) {
|
|
65
|
+
if (value)
|
|
66
|
+
await this.setOn();
|
|
67
|
+
else
|
|
68
|
+
await this.setOff();
|
|
69
|
+
}
|
|
70
|
+
// Unknown / non-writable property — ignored.
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Sensor, SensorType, SensorCategory } from './base.js';
|
|
2
|
+
/**
|
|
3
|
+
* Properties for temperature sensors
|
|
4
|
+
*
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
7
|
+
export var TemperatureProperty;
|
|
8
|
+
(function (TemperatureProperty) {
|
|
9
|
+
/** Current temperature in degrees Celsius */
|
|
10
|
+
TemperatureProperty["Current"] = "current";
|
|
11
|
+
})(TemperatureProperty || (TemperatureProperty = {}));
|
|
12
|
+
/** Temperature info sensor. Reports current temperature in °C. */
|
|
13
|
+
export class TemperatureInfo extends Sensor {
|
|
14
|
+
type = SensorType.Temperature;
|
|
15
|
+
category = SensorCategory.Info;
|
|
16
|
+
constructor(name = 'Temperature') {
|
|
17
|
+
super(name);
|
|
18
|
+
this._writeState({ [TemperatureProperty.Current]: 20 });
|
|
19
|
+
}
|
|
20
|
+
get current() {
|
|
21
|
+
return this.props.current;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Report a new temperature reading. Clamped to [-270, 100] °C.
|
|
25
|
+
*
|
|
26
|
+
* @param value - Temperature reading in degrees Celsius.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* temperature.setCurrent(21.5);
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
setCurrent(value) {
|
|
34
|
+
this._writeState({ [TemperatureProperty.Current]: Math.max(-270, Math.min(100, value)) });
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Read-only sensor: external writes are ignored. Reading via `setCurrent` is plugin-only.
|
|
38
|
+
*
|
|
39
|
+
* Called by the cross-process plugin host when a generic property write is received.
|
|
40
|
+
* Temperature sensors have no externally writable properties, so the parameters are
|
|
41
|
+
* unused (underscore-prefixed) and the call is a no-op.
|
|
42
|
+
*
|
|
43
|
+
* @param _property - Unused — temperature sensors expose no writable properties.
|
|
44
|
+
*
|
|
45
|
+
* @param _value - Unused — temperature sensors expose no writable properties.
|
|
46
|
+
*
|
|
47
|
+
* @internal
|
|
48
|
+
*/
|
|
49
|
+
updateValue(_property, _value) {
|
|
50
|
+
// No-op — temperature is reported by the plugin, not set externally.
|
|
51
|
+
}
|
|
52
|
+
}
|
package/dist/storage/index.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
export * from './storages.js';
|
|
1
|
+
export {};
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
2
|
+
import { defineConfig } from 'vitepress';
|
|
3
|
+
|
|
4
|
+
const require = createRequire(import.meta.url);
|
|
5
|
+
const typedocSidebar = require('../api/typedoc-sidebar.json');
|
|
6
|
+
|
|
7
|
+
// https://vitepress.dev/reference/site-config
|
|
8
|
+
export default defineConfig({
|
|
9
|
+
srcDir: '.',
|
|
10
|
+
base: '/sdk/node/',
|
|
11
|
+
title: 'camera.ui Node SDK',
|
|
12
|
+
description: 'TypeScript SDK for building camera.ui plugins',
|
|
13
|
+
lastUpdated: true,
|
|
14
|
+
head: [
|
|
15
|
+
['link', { rel: 'icon', type: 'image/x-icon', sizes: '32x32', href: '/sdk/node/favicon.ico' }],
|
|
16
|
+
['link', { rel: 'icon', type: 'image/x-icon', sizes: '16x16', href: '/sdk/node/favicon-16.ico' }],
|
|
17
|
+
['link', { rel: 'apple-touch-icon', sizes: '180x180', href: '/sdk/node/apple-touch-icon.png' }],
|
|
18
|
+
['meta', { name: 'theme-color', content: '#df2a4c' }],
|
|
19
|
+
],
|
|
20
|
+
themeConfig: {
|
|
21
|
+
logo: '/logo.svg',
|
|
22
|
+
|
|
23
|
+
// typedocSidebar entries are alphabetical:
|
|
24
|
+
// [0] camera, [1] manager, [2] observable, [3] plugin,
|
|
25
|
+
// [4] sensor, [5] storage, [6] types
|
|
26
|
+
sidebar: [
|
|
27
|
+
{
|
|
28
|
+
text: 'Plugin API',
|
|
29
|
+
items: typedocSidebar[3].items,
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
text: 'Camera',
|
|
33
|
+
items: typedocSidebar[0].items,
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
text: 'Sensors',
|
|
37
|
+
items: typedocSidebar[4].items,
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
text: 'Storage & Schema',
|
|
41
|
+
items: typedocSidebar[5].items,
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
text: 'Manager',
|
|
45
|
+
items: typedocSidebar[1].items,
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
text: 'Observable',
|
|
49
|
+
items: typedocSidebar[2].items,
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
text: 'Types',
|
|
53
|
+
items: typedocSidebar[6].items,
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
text: 'Plugin Guide',
|
|
57
|
+
link: '/examples/getting-started',
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
|
|
61
|
+
search: {
|
|
62
|
+
provider: 'local',
|
|
63
|
+
},
|
|
64
|
+
|
|
65
|
+
socialLinks: [
|
|
66
|
+
{ icon: 'github', link: 'https://github.com/seydx/camera.ui' },
|
|
67
|
+
{ icon: 'discord', link: 'https://discord.gg/bBGnGcbz8N' },
|
|
68
|
+
{
|
|
69
|
+
icon: {
|
|
70
|
+
svg: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill="currentColor" d="M20 10.04a2.18 2.18 0 0 0-3.7-1.55a10.7 10.7 0 0 0-5.79-1.83l.99-4.65l3.23.69a1.55 1.55 0 1 0 .15-.74l-3.59-.76a.37.37 0 0 0-.44.28l-1.1 5.18a10.74 10.74 0 0 0-5.87 1.83a2.19 2.19 0 1 0-2.41 3.59a4 4 0 0 0-.05.66c0 3.36 3.91 6.09 8.74 6.09s8.74-2.73 8.74-6.09a4 4 0 0 0-.05-.66A2.19 2.19 0 0 0 20 10.04m-15 1.56a1.56 1.56 0 1 1 1.56 1.56A1.56 1.56 0 0 1 5 11.6m8.71 4.13c-1.07.81-2.39 1.21-3.71 1.16a5.85 5.85 0 0 1-3.71-1.16a.4.4 0 1 1 .55-.59A4.94 4.94 0 0 0 10 16.1a4.94 4.94 0 0 0 3.16-.96a.41.41 0 0 1 .57.04a.41.41 0 0 1-.02.55m-.16-2.55a1.56 1.56 0 1 1 1.56-1.56a1.56 1.56 0 0 1-1.55 1.56z"/></svg>',
|
|
71
|
+
},
|
|
72
|
+
link: 'https://www.reddit.com/r/cameraui/',
|
|
73
|
+
ariaLabel: 'Reddit',
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
},
|
|
77
|
+
});
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
@import 'vitepress/dist/client/theme-default/styles/vars.css';
|
|
2
|
+
|
|
3
|
+
/* camera.ui brand colors — mirror ui/src/plugins/preset.ts */
|
|
4
|
+
:root {
|
|
5
|
+
--cui-primary-50: #fdf4f6;
|
|
6
|
+
--cui-primary-100: #f7ccd4;
|
|
7
|
+
--cui-primary-200: #f1a3b2;
|
|
8
|
+
--cui-primary-300: #eb7b90;
|
|
9
|
+
--cui-primary-400: #e5526e;
|
|
10
|
+
--cui-primary-500: #df2a4c;
|
|
11
|
+
--cui-primary-600: #be2441;
|
|
12
|
+
--cui-primary-700: #9c1d35;
|
|
13
|
+
--cui-primary-800: #7b172a;
|
|
14
|
+
--cui-primary-900: #59111e;
|
|
15
|
+
--cui-primary-950: #380b13;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
:root {
|
|
19
|
+
--vp-c-brand-1: var(--cui-primary-500);
|
|
20
|
+
--vp-c-brand-2: var(--cui-primary-600);
|
|
21
|
+
--vp-c-brand-3: var(--cui-primary-700);
|
|
22
|
+
--vp-c-brand-soft: rgba(223, 42, 76, 0.14);
|
|
23
|
+
|
|
24
|
+
--vp-c-default-1: var(--vp-c-gray-1);
|
|
25
|
+
--vp-c-default-2: var(--vp-c-gray-2);
|
|
26
|
+
--vp-c-default-3: var(--vp-c-gray-3);
|
|
27
|
+
--vp-c-default-soft: var(--vp-c-gray-soft);
|
|
28
|
+
|
|
29
|
+
--vp-button-brand-border: transparent;
|
|
30
|
+
--vp-button-brand-text: #ffffff;
|
|
31
|
+
--vp-button-brand-bg: var(--cui-primary-500);
|
|
32
|
+
--vp-button-brand-hover-border: transparent;
|
|
33
|
+
--vp-button-brand-hover-text: #ffffff;
|
|
34
|
+
--vp-button-brand-hover-bg: var(--cui-primary-600);
|
|
35
|
+
--vp-button-brand-active-border: transparent;
|
|
36
|
+
--vp-button-brand-active-text: #ffffff;
|
|
37
|
+
--vp-button-brand-active-bg: var(--cui-primary-700);
|
|
38
|
+
|
|
39
|
+
--vp-home-hero-name-color: transparent;
|
|
40
|
+
--vp-home-hero-name-background: linear-gradient(
|
|
41
|
+
135deg,
|
|
42
|
+
var(--cui-primary-500) 0%,
|
|
43
|
+
var(--cui-primary-700) 100%
|
|
44
|
+
);
|
|
45
|
+
--vp-home-hero-image-background-image: linear-gradient(
|
|
46
|
+
135deg,
|
|
47
|
+
rgba(223, 42, 76, 0.32) 0%,
|
|
48
|
+
rgba(123, 23, 42, 0.32) 100%
|
|
49
|
+
);
|
|
50
|
+
--vp-home-hero-image-filter: blur(56px);
|
|
51
|
+
|
|
52
|
+
--vp-custom-block-tip-border: transparent;
|
|
53
|
+
--vp-custom-block-tip-text: var(--cui-primary-700);
|
|
54
|
+
--vp-custom-block-tip-bg: var(--vp-c-brand-soft);
|
|
55
|
+
--vp-custom-block-tip-code-bg: var(--vp-c-brand-soft);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/* dark surface palette mirrors ui preset.ts (neutral grey, not slate) */
|
|
59
|
+
.dark {
|
|
60
|
+
--cui-surface-0: #ffffff;
|
|
61
|
+
--cui-surface-50: #f5f5f5;
|
|
62
|
+
--cui-surface-100: #d1d1d1;
|
|
63
|
+
--cui-surface-200: #adadad;
|
|
64
|
+
--cui-surface-300: #898989;
|
|
65
|
+
--cui-surface-400: #646464;
|
|
66
|
+
--cui-surface-500: #404040;
|
|
67
|
+
--cui-surface-600: #363636;
|
|
68
|
+
--cui-surface-700: #2d2d2d;
|
|
69
|
+
--cui-surface-800: #232323;
|
|
70
|
+
--cui-surface-850: #1d1d1d;
|
|
71
|
+
--cui-surface-900: #1a1a1a;
|
|
72
|
+
--cui-surface-925: #161616;
|
|
73
|
+
--cui-surface-950: #101010;
|
|
74
|
+
--cui-surface-1000: #0d0d0d;
|
|
75
|
+
|
|
76
|
+
--vp-c-brand-1: var(--cui-primary-400);
|
|
77
|
+
--vp-c-brand-2: var(--cui-primary-300);
|
|
78
|
+
--vp-c-brand-3: var(--cui-primary-200);
|
|
79
|
+
--vp-c-brand-soft: rgba(229, 82, 110, 0.16);
|
|
80
|
+
|
|
81
|
+
--vp-c-bg: var(--cui-surface-900);
|
|
82
|
+
--vp-c-bg-alt: var(--cui-surface-950);
|
|
83
|
+
--vp-c-bg-elv: var(--cui-surface-800);
|
|
84
|
+
--vp-c-bg-soft: var(--cui-surface-850);
|
|
85
|
+
|
|
86
|
+
--vp-c-divider: var(--cui-surface-800);
|
|
87
|
+
--vp-c-gutter: var(--cui-surface-950);
|
|
88
|
+
--vp-c-border: var(--cui-surface-700);
|
|
89
|
+
|
|
90
|
+
--vp-c-default-1: var(--cui-surface-800);
|
|
91
|
+
--vp-c-default-2: var(--cui-surface-700);
|
|
92
|
+
--vp-c-default-3: var(--cui-surface-600);
|
|
93
|
+
--vp-c-default-soft: rgba(64, 64, 64, 0.4);
|
|
94
|
+
|
|
95
|
+
--vp-c-text-1: rgba(255, 255, 255, 0.92);
|
|
96
|
+
--vp-c-text-2: rgba(255, 255, 255, 0.66);
|
|
97
|
+
--vp-c-text-3: rgba(255, 255, 255, 0.42);
|
|
98
|
+
|
|
99
|
+
--vp-code-bg: var(--cui-surface-925);
|
|
100
|
+
--vp-code-block-bg: var(--cui-surface-925);
|
|
101
|
+
|
|
102
|
+
--vp-button-brand-text: #ffffff;
|
|
103
|
+
--vp-button-brand-bg: var(--cui-primary-500);
|
|
104
|
+
--vp-button-brand-hover-bg: var(--cui-primary-400);
|
|
105
|
+
--vp-button-brand-active-bg: var(--cui-primary-600);
|
|
106
|
+
|
|
107
|
+
--vp-custom-block-tip-text: var(--cui-primary-200);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/* Pull search/box accents in line with brand */
|
|
111
|
+
.dark .DocSearch {
|
|
112
|
+
--docsearch-primary-color: var(--cui-primary-400);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.DocSearch {
|
|
116
|
+
--docsearch-primary-color: var(--cui-primary-500);
|
|
117
|
+
}
|
package/docs/index.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# camera.ui Node SDK
|
|
2
|
+
|
|
3
|
+
TypeScript SDK for building plugins that extend [camera.ui](https://github.com/seydx/camera.ui) — add cameras, run motion / object / face / license-plate / audio detection, deliver notifications, and more.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @camera.ui/sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Next steps
|
|
12
|
+
|
|
13
|
+
- **[Plugin Guide](/examples/getting-started)** — everything you need to ship a Node plugin in one page: contract, lifecycle, sensors, storage, optional interfaces.
|
|
14
|
+
- **[API Reference](/api/)** — module-by-module reference auto-generated from JSDoc.
|
|
15
|
+
|
|
16
|
+
For complete production plugins to study, see [`plugins/`](https://github.com/seydx/camera.ui/tree/main/plugins) in the camera.ui repo.
|
package/docs/logo.png
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 233.63 233.63"><defs><style>.cls-1{fill:url(#dark_wine);}.cls-2{fill:url(#light_wine);}.cls-3{fill:none;stroke:#000;stroke-miterlimit:10;opacity:0;}.cls-4{fill:#c5c6c8;}.cls-5{fill:#1a1e21;stroke:#3a3a3a;stroke-width:2px;}.cls-6{fill:#fff;}</style><linearGradient id="dark_wine" x1="87.36" y1="158.67" x2="87.36" y2="59.85" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#730000"/><stop offset="0.49" stop-color="#a51733"/></linearGradient><linearGradient id="light_wine" x1="113.06" y1="197.59" x2="113.06" y2="80.87" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#f44a6b"/><stop offset="0.28" stop-color="#df294c"/></linearGradient></defs><g id="CameraUI_U"><path id="U_Left" class="cls-1" d="M47.05,119.47s7.58,16,14.12,23.42a45.28,45.28,0,0,0,16.37,11.86A49.46,49.46,0,0,0,99,158.62c9.43-.46,20.55-3.87,29.24-11.86-3.9,2.5-9.87,5.1-15.9,4.77a25.63,25.63,0,0,1-18.38-9.09c-9.39-10.31-7.62-28.35-7.75-32.68-.35-11.42.77-21.92-1.76-36.19-.46-2.64-1.79-5.19-4.55-8-1.83-1.86-8.4-5.75-13.42-5.74-7.31,0-12.95,3.71-15.38,7.84-2,3.41-3.06,4.22-4.23,25.08a217.23,217.23,0,0,0,.22,26.76Z" transform="translate(0.5 0.5)"/><path id="U_Right" class="cls-2" d="M144.12,89.6a16.24,16.24,0,0,1,4.06-4.9c4.16-3.4,9-3.67,10.92-3.82a19.7,19.7,0,0,1,12.53,4.58c1.19,1,6.11,5.58,7.13,17.29.73,8.51,3.31,65.93-37,87.14-4.22,2.22-18,9.25-35.66,7.38a62.43,62.43,0,0,1-20.8-6.11,65.8,65.8,0,0,1-18.89-14.23c-20.21-21.67-19.36-57.46-19.36-57.46s7.58,16,14.12,23.42a45.28,45.28,0,0,0,16.37,11.86A49.46,49.46,0,0,0,99,158.62c11.66-.57,25.93-5.64,35-18.32C143.52,126.8,138.46,100.51,144.12,89.6Z" transform="translate(0.5 0.5)"/></g><g id="CameraUI_Lens"><circle id="ellipse" class="cls-3" cx="116.81" cy="116.81" r="116.31"/><g id="lens"><circle id="lens_bg" class="cls-4" cx="159.13" cy="58.39" r="18.66"/><path id="lens_inner" class="cls-5" d="M169.64,58.31a11,11,0,1,1-22,0c0-6.08,4.93-11.86,11-11.86S169.64,52.23,169.64,58.31Z" transform="translate(0.5 0.5)"/><g id="reflections"><ellipse id="dot_1" class="cls-6" cx="174.36" cy="53.69" rx="1.84" ry="1.42"/><ellipse id="dot_2" class="cls-6" cx="174.36" cy="57.08" rx="1.84" ry="1.42"/><ellipse id="dot_3" class="cls-6" cx="174.36" cy="60.46" rx="1.84" ry="1.42"/><circle id="dot_4" class="cls-6" cx="164.09" cy="63.77" r="1.66"/><path id="wide_1" class="cls-6" d="M156.63,48.9c-1.07-.88-5.52,3.09-6.31,5.43a1.53,1.53,0,0,0,0,1.26c.43.69,1.73.61,2.19.54,2.68-.44,4.71-4.09,4.8-4.37A3.21,3.21,0,0,0,156.63,48.9Z" transform="translate(0.5 0.5)"/></g></g></g></svg>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Plugin Guide
|
|
2
|
+
|
|
3
|
+
Everything you need to ship a camera.ui plugin in one page: contract, lifecycle, sensors, storage, optional interfaces (discovery, notifier, detection), and inter-plugin communication.
|
|
4
|
+
|
|
5
|
+
[Read the guide →](./getting-started.md)
|
|
6
|
+
|
|
7
|
+
For complete production plugins to read alongside, see [`plugins/`](https://github.com/seydx/camera.ui/tree/main/plugins) in the camera.ui repo.
|