@vdegenne/kokoro-standalone 0.0.0-stage → 0.1.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 CHANGED
@@ -1,3 +1,74 @@
1
- # Temporary Holding Version
1
+ # @vdegenne/kokoro-standalone
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Snar TS reactive controller using kokoro-js.
4
+ The difference with `@vdegenne/kokoro` is that you don't need a TTS server to generate speeches,
5
+ this library uses `kokoro-js` and `transformers.js` to generate the voices directly into the browser.
6
+
7
+ Only English support for now.
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ npm i -D @vdegenne/kokoro-standalone
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ```ts
18
+ import {KokoroClient} from '@vdegenne/kokoro-standalone';
19
+
20
+ const kokoro = new KokoroClient();
21
+
22
+ try {
23
+ await kokoro.connect(); // connect to the model
24
+ kokoro.play('Hello world.');
25
+ } catch (err) {
26
+ console.error(`Something went wrong. (${err})`);
27
+ }
28
+ ```
29
+
30
+ ### Arguments
31
+
32
+ ```ts
33
+ kokoro.play(
34
+ 'Hello world.', // text
35
+ // options
36
+ {
37
+ voiceId: 'af_sky',
38
+ speed: 1,
39
+ volume: 1,
40
+ },
41
+ );
42
+ ```
43
+
44
+ ### Controller
45
+
46
+ `kokoro` is a controller, you can bind it to a `LitElement` custom element.
47
+
48
+ ```ts
49
+ import {KokoroClient} from '@vdegenne/kokoro-standalone';
50
+ import {LitElement, customElement} from 'lit';
51
+ import {withController} from '@snar/lit';
52
+
53
+ const kokoro = new KokoroClient();
54
+
55
+ @customElement('settings-dialog')
56
+ @withController(kokoro)
57
+ class SettingsDialog extends LitElement {
58
+ // ...
59
+ }
60
+ ```
61
+
62
+ Use this in your store
63
+
64
+ ```js
65
+ @state() kokoroEnVoiceId: EnVoice = availableVoices.En[0]
66
+ @state() kokoroEnRandom = false
67
+ @state() kokoroEnSpeed = 1
68
+ ```
69
+
70
+ With imports being
71
+
72
+ ```js
73
+ import {availableVoices, EnVoice} from '@vdegenne/kokoro-standalone';
74
+ ```
package/lib/index.d.ts ADDED
@@ -0,0 +1,45 @@
1
+ import { ReactiveController } from '@snar/lit';
2
+ export declare const availableVoices: {
3
+ readonly En: readonly ['af_heart', 'af_aoede', 'af_bella', 'af_jessica', 'af_kore', 'af_nicole', 'af_nova', 'af_river', 'af_sarah', 'af_sky', 'af_alloy', 'am_adam', 'am_michael', 'am_echo', 'am_eric', 'am_fenrir', 'am_liam', 'am_onyx', 'am_puck', 'am_santa', 'bf_emma', 'bf_isabella', 'bf_alice', 'bf_lily', 'bm_george', 'bm_lewis', 'bm_daniel', 'bm_fable'];
4
+ };
5
+ export type EnVoice = (typeof availableVoices)['En'][number];
6
+ export type Language = keyof typeof availableVoices;
7
+ export type Voice = (typeof availableVoices)[Language][number];
8
+ interface KokoroVoice {
9
+ id: Voice;
10
+ description: string;
11
+ }
12
+ interface PlayOptions {
13
+ voiceId?: Voice;
14
+ speed?: number;
15
+ volume?: number;
16
+ }
17
+ export declare class KokoroClient extends ReactiveController {
18
+ state: 'disconnected' | 'connecting' | 'connection_error' | 'connected';
19
+ voices: KokoroVoice[];
20
+ private tts;
21
+ private initialization;
22
+ private initializationId;
23
+ private cache;
24
+ private currentAudios;
25
+ private pendingPlays;
26
+ connect({ reconnect }?: {
27
+ reconnect?: boolean;
28
+ }): Promise<void>;
29
+ disconnect(): void;
30
+ getAudio(text: string, { voiceId, speed }?: PlayOptions): Promise<Blob>;
31
+ play(text: string, { voiceId, speed, volume }?: PlayOptions): Promise<void>;
32
+ togglePlay(sentence: string, options?: PlayOptions): Promise<void>;
33
+ private generateAudio;
34
+ private playBlob;
35
+ private stop;
36
+ private getCacheKey;
37
+ getRandomVoiceId<L extends Language>({ lang, exclude, }: {
38
+ lang: L;
39
+ exclude?: (typeof availableVoices)[L][number][];
40
+ }): (typeof availableVoices)[L][number];
41
+ getVoiceTitleFromId(voiceId: Voice): "af_alloy" | "af_aoede" | "af_bella" | "af_heart" | "af_jessica" | "af_kore" | "af_nicole" | "af_nova" | "af_river" | "af_sarah" | "af_sky" | "am_adam" | "am_echo" | "am_eric" | "am_fenrir" | "am_liam" | "am_michael" | "am_onyx" | "am_puck" | "am_santa" | "bf_alice" | "bf_emma" | "bf_isabella" | "bf_lily" | "bm_daniel" | "bm_fable" | "bm_george" | "bm_lewis";
42
+ getVoiceIds(): ("af_alloy" | "af_aoede" | "af_bella" | "af_heart" | "af_jessica" | "af_kore" | "af_nicole" | "af_nova" | "af_river" | "af_sarah" | "af_sky" | "am_adam" | "am_echo" | "am_eric" | "am_fenrir" | "am_liam" | "am_michael" | "am_onyx" | "am_puck" | "am_santa" | "bf_alice" | "bf_emma" | "bf_isabella" | "bf_lily" | "bm_daniel" | "bm_fable" | "bm_george" | "bm_lewis")[];
43
+ }
44
+ export {};
45
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,kBAAkB,EAAQ,MAAM,WAAW,CAAC;AAIpD,eAAO,MAAM,eAAe;aAC3B,EAAE,YAAG,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU;CACzU,CAAC;AAEX,MAAM,MAAM,OAAO,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC;AAC7D,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,eAAe,CAAC;AACpD,MAAM,MAAM,KAAK,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC;AAE/D,UAAU,WAAW;IACpB,EAAE,EAAE,KAAK,CAAC;IACV,WAAW,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,WAAW;IACpB,OAAO,CAAC,EAAE,KAAK,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAID,qBAAa,YAAa,SAAQ,kBAAkB;IAC1C,KAAK,EACb,cAAc,GAAG,YAAY,GAAG,kBAAkB,GAAG,WAAW,CACjD;IAEP,MAAM,EAAE,WAAW,EAAE,CAAM;IAEpC,OAAO,CAAC,GAAG,CAA0B;IACrC,OAAO,CAAC,cAAc,CAAmC;IACzD,OAAO,CAAC,gBAAgB,CAAK;IAE7B,OAAO,CAAC,KAAK,CAAkC;IAE/C,OAAO,CAAC,aAAa,CAMjB;IAEJ,OAAO,CAAC,YAAY,CAAqB;IAEnC,OAAO,CAAC,EAAC,SAAiB,EAAC,GAAE;QAAC,SAAS,CAAC,EAAE,OAAO,CAAA;KAAM,iBAoD5D;IAED,UAAU,SAWT;IAEK,QAAQ,CACb,IAAI,EAAE,MAAM,EACZ,EAAC,OAAoB,EAAE,KAAS,EAAC,GAAE,WAAgB,GACjD,OAAO,CAAC,IAAI,CAAC,CAuBf;IAEK,IAAI,CACT,IAAI,EAAE,MAAM,EACZ,EAAC,OAAoB,EAAE,KAAS,EAAE,MAAU,EAAC,GAAE,WAAgB,iBAkC/D;IAEK,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,iBAO3D;YAEa,aAAa;YAmBb,QAAQ;IAyDtB,OAAO,CAAC,IAAI;IA0BZ,OAAO,CAAC,WAAW;IAInB,gBAAgB,CAAC,CAAC,SAAS,QAAQ,EAAE,EACpC,IAAI,EACJ,OAAY,GACZ,EAAE;QACF,IAAI,EAAE,CAAC,CAAC;QACR,OAAO,CAAC,EAAE,CAAC,OAAO,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;KAChD,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAUtC;IAED,mBAAmB,CAAC,OAAO,EAAE,KAAK,4WAEjC;IAED,WAAW,iXAEV;CACD"}
package/lib/index.js ADDED
@@ -0,0 +1,223 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { ReactiveController, state } from '@snar/lit';
8
+ import { KokoroTTS } from 'kokoro-js';
9
+ // prettier-ignore
10
+ export const availableVoices = {
11
+ En: ['af_heart', 'af_aoede', 'af_bella', 'af_jessica', 'af_kore', 'af_nicole', 'af_nova', 'af_river', 'af_sarah', 'af_sky', 'af_alloy', 'am_adam', 'am_michael', 'am_echo', 'am_eric', 'am_fenrir', 'am_liam', 'am_onyx', 'am_puck', 'am_santa', 'bf_emma', 'bf_isabella', 'bf_alice', 'bf_lily', 'bm_george', 'bm_lewis', 'bm_daniel', 'bm_fable'],
12
+ };
13
+ export class KokoroClient extends ReactiveController {
14
+ constructor() {
15
+ super(...arguments);
16
+ this.state = 'disconnected';
17
+ this.voices = [];
18
+ this.tts = null;
19
+ this.initialization = null;
20
+ this.initializationId = 0;
21
+ this.cache = new Map();
22
+ this.currentAudios = new Map();
23
+ this.pendingPlays = new Set();
24
+ }
25
+ async connect({ reconnect = false } = {}) {
26
+ if (this.state === 'connected' && !reconnect) {
27
+ return;
28
+ }
29
+ if (this.initialization && !reconnect) {
30
+ await this.initialization;
31
+ return;
32
+ }
33
+ const initializationId = ++this.initializationId;
34
+ this.state = 'connecting';
35
+ const initialization = KokoroTTS.from_pretrained('onnx-community/Kokoro-82M-v1.0-ONNX', {
36
+ dtype: 'q8',
37
+ device: 'wasm',
38
+ });
39
+ this.initialization = initialization;
40
+ try {
41
+ const tts = await initialization;
42
+ if (initializationId !== this.initializationId) {
43
+ return;
44
+ }
45
+ this.tts = tts;
46
+ this.voices = availableVoices.En.map((id) => ({
47
+ id,
48
+ description: '',
49
+ }));
50
+ this.state = 'connected';
51
+ }
52
+ catch (error) {
53
+ if (initializationId === this.initializationId) {
54
+ this.tts = null;
55
+ this.voices = [];
56
+ this.state = 'connection_error';
57
+ }
58
+ throw error;
59
+ }
60
+ finally {
61
+ if (this.initialization === initialization) {
62
+ this.initialization = null;
63
+ }
64
+ }
65
+ }
66
+ disconnect() {
67
+ ++this.initializationId;
68
+ this.initialization = null;
69
+ this.stop();
70
+ this.tts = null;
71
+ this.voices = [];
72
+ this.cache.clear();
73
+ this.state = 'disconnected';
74
+ }
75
+ async getAudio(text, { voiceId = 'af_heart', speed = 1 } = {}) {
76
+ if (this.state !== 'connected' || !this.tts) {
77
+ throw new Error('Kokoro is not connected');
78
+ }
79
+ const key = this.getCacheKey(text, voiceId, speed);
80
+ const cached = this.cache.get(key);
81
+ if (cached) {
82
+ return cached instanceof Promise ? cached : Promise.resolve(cached);
83
+ }
84
+ const promise = this.generateAudio(text, voiceId, speed);
85
+ this.cache.set(key, promise);
86
+ try {
87
+ const audio = await promise;
88
+ this.cache.set(key, audio);
89
+ return audio;
90
+ }
91
+ catch (error) {
92
+ this.cache.delete(key);
93
+ throw error;
94
+ }
95
+ }
96
+ async play(text, { voiceId = 'af_heart', speed = 1, volume = 1 } = {}) {
97
+ if (this.state !== 'connected') {
98
+ throw new Error('Kokoro is not connected');
99
+ }
100
+ const key = this.getCacheKey(text, voiceId, speed);
101
+ if (this.pendingPlays.has(key)) {
102
+ return;
103
+ }
104
+ const current = this.currentAudios.get(key);
105
+ if (current) {
106
+ current.audio.currentTime = 0;
107
+ current.audio.volume = Math.max(0, Math.min(1, volume));
108
+ await current.audio.play();
109
+ return;
110
+ }
111
+ this.pendingPlays.add(key);
112
+ try {
113
+ const blob = await this.getAudio(text, { voiceId, speed });
114
+ if (this.state !== 'connected') {
115
+ return;
116
+ }
117
+ await this.playBlob(blob, key, volume);
118
+ }
119
+ finally {
120
+ this.pendingPlays.delete(key);
121
+ }
122
+ }
123
+ async togglePlay(sentence, options = {}) {
124
+ if (this.currentAudios.size > 0) {
125
+ this.stop();
126
+ return;
127
+ }
128
+ return this.play(sentence, options);
129
+ }
130
+ async generateAudio(text, voiceId, speed) {
131
+ const tts = this.tts;
132
+ if (!tts) {
133
+ throw new Error('Kokoro is not connected');
134
+ }
135
+ const audio = await tts.generate(text, {
136
+ voice: voiceId,
137
+ speed,
138
+ });
139
+ return audio.toBlob();
140
+ }
141
+ async playBlob(blob, key, volume) {
142
+ const url = URL.createObjectURL(blob);
143
+ const audio = new Audio(url);
144
+ audio.volume = Math.max(0, Math.min(1, volume));
145
+ this.currentAudios.set(key, {
146
+ audio,
147
+ resolve: () => { },
148
+ });
149
+ try {
150
+ await audio.play();
151
+ await new Promise((resolve, reject) => {
152
+ const current = this.currentAudios.get(key);
153
+ if (current?.audio === audio) {
154
+ current.resolve = resolve;
155
+ }
156
+ audio.addEventListener('ended', () => {
157
+ if (this.currentAudios.get(key)?.audio === audio) {
158
+ this.currentAudios.delete(key);
159
+ }
160
+ URL.revokeObjectURL(url);
161
+ resolve();
162
+ }, { once: true });
163
+ audio.addEventListener('error', () => {
164
+ if (this.currentAudios.get(key)?.audio === audio) {
165
+ this.currentAudios.delete(key);
166
+ }
167
+ URL.revokeObjectURL(url);
168
+ reject(new Error('Audio playback failed'));
169
+ }, { once: true });
170
+ });
171
+ }
172
+ catch (error) {
173
+ if (this.currentAudios.get(key)?.audio === audio) {
174
+ this.currentAudios.delete(key);
175
+ }
176
+ URL.revokeObjectURL(url);
177
+ throw error;
178
+ }
179
+ }
180
+ stop(key) {
181
+ if (key) {
182
+ const current = this.currentAudios.get(key);
183
+ if (!current) {
184
+ return;
185
+ }
186
+ current.audio.pause();
187
+ current.audio.currentTime = 0;
188
+ this.currentAudios.delete(key);
189
+ current.resolve();
190
+ return;
191
+ }
192
+ for (const current of this.currentAudios.values()) {
193
+ current.audio.pause();
194
+ current.audio.currentTime = 0;
195
+ current.resolve();
196
+ }
197
+ this.currentAudios.clear();
198
+ }
199
+ getCacheKey(sentence, voiceId, speed) {
200
+ return `${voiceId}:${speed}:${sentence}`;
201
+ }
202
+ getRandomVoiceId({ lang, exclude = [], }) {
203
+ const voices = availableVoices[lang].filter((voice) => !exclude.includes(voice));
204
+ if (voices.length === 0) {
205
+ throw new Error(`Kokoro has no available voices for ${lang}`);
206
+ }
207
+ return voices[Math.floor(Math.random() * voices.length)];
208
+ }
209
+ getVoiceTitleFromId(voiceId) {
210
+ return voiceId;
211
+ }
212
+ getVoiceIds() {
213
+ return this.voices.map((voice) => voice.id);
214
+ }
215
+ }
216
+ __decorate([
217
+ state()
218
+ ], KokoroClient.prototype, "state", void 0);
219
+ __decorate([
220
+ state()
221
+ ], KokoroClient.prototype, "voices", void 0);
222
+ // export const kokoro = new KokoroClient();
223
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { KokoroClient, Language } from './index.js';
2
+ /**
3
+ * Imports you'll need:
4
+ *
5
+ * import '@material/web/select/filled-select.js';
6
+ * import '@material/web/select/select-option.js';
7
+ * import '@material/web/button/filled-tonal-button.js';
8
+ * import '@material/web/select/select-option.js';
9
+ * import '@material/web/list/list-item.js';
10
+ * import '@material/web/switch/switch.js';
11
+ * import '@material/web/progress/circular-progress.js';
12
+ * import '@material/web/icon/icon.js'
13
+ * import '@material/web/slider/slider.js';
14
+ */
15
+ export declare function kokoroSettingsTemplate(kokoro: KokoroClient, store: any, lang?: Language): "Kokoro is disconnected" | import("lit-html").TemplateResult<1>;
16
+ //# sourceMappingURL=settings-template.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings-template.d.ts","sourceRoot":"","sources":["../src/settings-template.ts"],"names":[],"mappings":"AAEA,OAAO,EAAkB,YAAY,EAAE,QAAQ,EAAC,MAAM,YAAY,CAAC;AAEnE;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CACrC,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,GAAG,EACV,IAAI,GAAE,QAAe,mEAwDrB"}
@@ -0,0 +1,70 @@
1
+ import { SELECT, SLIDER, SWITCH } from '@vdegenne/forms/FormBuilder.js';
2
+ import { html } from 'lit-html';
3
+ import { availableVoices } from './index.js';
4
+ /**
5
+ * Imports you'll need:
6
+ *
7
+ * import '@material/web/select/filled-select.js';
8
+ * import '@material/web/select/select-option.js';
9
+ * import '@material/web/button/filled-tonal-button.js';
10
+ * import '@material/web/select/select-option.js';
11
+ * import '@material/web/list/list-item.js';
12
+ * import '@material/web/switch/switch.js';
13
+ * import '@material/web/progress/circular-progress.js';
14
+ * import '@material/web/icon/icon.js'
15
+ * import '@material/web/slider/slider.js';
16
+ */
17
+ export function kokoroSettingsTemplate(kokoro, store, lang = 'En') {
18
+ switch (kokoro.state) {
19
+ case 'disconnected':
20
+ return 'Kokoro is disconnected';
21
+ case 'connecting':
22
+ return html `<!-- -->
23
+ <md-list-item>
24
+ <md-circular-progress
25
+ indeterminate
26
+ slot="start"
27
+ ></md-circular-progress>
28
+ Please wait
29
+ </md-list-item>
30
+ <!-- -->`;
31
+ case 'connection_error':
32
+ return html `<!-- -->
33
+ <md-list-item>
34
+ <md-icon slot="start" style="color: var(--md-sys-color-error)"
35
+ >error</md-icon
36
+ >
37
+ <div slot="headline" style="color: var(--md-sys-color-error)">
38
+ Kokoro server unreachable
39
+ </div>
40
+ <md-filled-tonal-button
41
+ form=""
42
+ slot="end"
43
+ @click="${() => kokoro.connect()}"
44
+ >Try again</md-filled-tonal-button
45
+ >
46
+ </md-list-item>
47
+ <!-- -->`;
48
+ case 'connected': {
49
+ const voices = availableVoices[lang];
50
+ const hasMultipleVoices = voices.length > 1;
51
+ return html `<!-- -->
52
+ ${SELECT('Voice', store, `kokoro${lang}VoiceId`, voices, {
53
+ disabled: !hasMultipleVoices || store[`kokoro${lang}Random`],
54
+ supportingText: !hasMultipleVoices
55
+ ? 'Only one supported voice'
56
+ : undefined,
57
+ })}
58
+ ${hasMultipleVoices
59
+ ? SWITCH('Random voice', store, `kokoro${lang}Random`)
60
+ : null}
61
+ ${SLIDER('Voice speed', store, `kokoro${lang}Speed`, {
62
+ min: 0.1,
63
+ max: 1.9,
64
+ step: 0.1,
65
+ })}
66
+ <!-- -->`;
67
+ }
68
+ }
69
+ }
70
+ //# sourceMappingURL=settings-template.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings-template.js","sourceRoot":"","sources":["../src/settings-template.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAC,MAAM,gCAAgC,CAAC;AACtE,OAAO,EAAC,IAAI,EAAC,MAAM,UAAU,CAAC;AAC9B,OAAO,EAAC,eAAe,EAAyB,MAAM,YAAY,CAAC;AAEnE;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,sBAAsB,CACrC,MAAoB,EACpB,KAAU,EACV,IAAI,GAAa,IAAI;IAErB,QAAQ,MAAM,CAAC,KAAK,EAAE,CAAC;QACtB,KAAK,cAAc;YAClB,OAAO,wBAAwB,CAAC;QACjC,KAAK,YAAY;YAChB,OAAO,IAAI,CAAA;;;;;;;;aAQD,CAAC;QACZ,KAAK,kBAAkB;YACtB,OAAO,IAAI,CAAA;;;;;;;;;;;gBAWE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE;;;;aAIzB,CAAC;QACZ,KAAK,WAAW,EAAE,CAAC;YAClB,MAAM,MAAM,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;YACrC,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;YAE5C,OAAO,IAAI,CAAA;MACR,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,IAAI,SAAS,EAAE,MAAM,EAAE;gBACxD,QAAQ,EAAE,CAAC,iBAAiB,IAAI,KAAK,CAAC,SAAS,IAAI,QAAQ,CAAC;gBAC5D,cAAc,EAAE,CAAC,iBAAiB;oBACjC,CAAC,CAAC,0BAA0B;oBAC5B,CAAC,CAAC,SAAS;aACZ,CAAC;MAED,iBAAiB;gBAChB,CAAC,CAAC,MAAM,CAAC,cAAc,EAAE,KAAK,EAAE,SAAS,IAAI,QAAQ,CAAC;gBACtD,CAAC,CAAC,IACJ;MACE,MAAM,CAAC,aAAa,EAAE,KAAK,EAAE,SAAS,IAAI,OAAO,EAAE;gBACpD,GAAG,EAAE,GAAG;gBACR,GAAG,EAAE,GAAG;gBACR,IAAI,EAAE,GAAG;aACT,CAAC;aACO,CAAC;QACZ,CAAC;IACF,CAAC;AACF,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,45 @@
1
1
  {
2
- "name": "@vdegenne/kokoro-standalone",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
2
+ "name": "@vdegenne/kokoro-standalone",
3
+ "version": "0.1.2",
4
+ "description": "Snar TS reactive controller using kokoro-js",
5
+ "type": "module",
6
+ "exports": {
7
+ ".": {
8
+ "import": "./lib/index.js",
9
+ "types": "./lib/index.d.ts"
10
+ },
11
+ "./settings-template.js": {
12
+ "import": "./lib/settings-template.js",
13
+ "types": "./lib/settings-template.d.ts"
14
+ }
15
+ },
16
+ "files": [
17
+ "./lib"
18
+ ],
19
+ "scripts": {
20
+ "build": "wireit"
21
+ },
22
+ "wireit": {
23
+ "build": {
24
+ "command": "tsc --pretty",
25
+ "clean": "if-file-deleted",
26
+ "files": [
27
+ "./tsconfig.json",
28
+ "./src"
29
+ ],
30
+ "output": [
31
+ "./lib"
32
+ ]
33
+ }
34
+ },
35
+ "devDependencies": {
36
+ "typescript": "^7.0.2",
37
+ "wireit": "^0.14.13"
38
+ },
39
+ "dependencies": {
40
+ "@snar/lit": "^1.8.1",
41
+ "@vdegenne/forms": "^0.1.90",
42
+ "kokoro-js": "^1.2.1",
43
+ "lit-html": "^3.3.3"
44
+ }
45
+ }