@callembed/vue 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/LICENSE +21 -0
- package/README.md +79 -2
- package/dist/index.cjs +467 -0
- package/dist/index.d.cts +241 -0
- package/dist/index.d.ts +241 -0
- package/dist/index.js +444 -0
- package/dist/styles.css +89 -0
- package/package.json +80 -4
package/dist/index.js
ADDED
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
import { CallEmbed, CallEmbedError } from '@callembed/sdk';
|
|
2
|
+
import { defineComponent, ref, computed, watch, reactive, provide, h, inject } from 'vue';
|
|
3
|
+
import { resolveCopy, friendlyErrorMessage } from '@callembed/sdk/ui';
|
|
4
|
+
export { enCopy, friendlyErrorMessage, resolveCopy, zhTwCopy } from '@callembed/sdk/ui';
|
|
5
|
+
|
|
6
|
+
// src/provider.ts
|
|
7
|
+
|
|
8
|
+
// src/types.ts
|
|
9
|
+
function toUiState(status) {
|
|
10
|
+
switch (status) {
|
|
11
|
+
case "connecting":
|
|
12
|
+
case "ringing":
|
|
13
|
+
return "ringing";
|
|
14
|
+
case "answered":
|
|
15
|
+
return "connected";
|
|
16
|
+
case "ended":
|
|
17
|
+
return "ended";
|
|
18
|
+
case "error":
|
|
19
|
+
return "error";
|
|
20
|
+
case "idle":
|
|
21
|
+
default:
|
|
22
|
+
return "idle";
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
var CALL_EMBED_KEY = /* @__PURE__ */ Symbol("callembed");
|
|
26
|
+
|
|
27
|
+
// src/provider.ts
|
|
28
|
+
function toErrorState(err) {
|
|
29
|
+
if (err instanceof CallEmbedError) {
|
|
30
|
+
return { code: err.code, message: err.message };
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
code: "call_failed",
|
|
34
|
+
message: err instanceof Error ? err.message : String(err)
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function isActiveStatus(status) {
|
|
38
|
+
return status === "connecting" || status === "ringing" || status === "answered";
|
|
39
|
+
}
|
|
40
|
+
function bindCall(call, handlers) {
|
|
41
|
+
const offs = [
|
|
42
|
+
call.on("statusChange", ({ status }) => {
|
|
43
|
+
handlers.setStatus(status);
|
|
44
|
+
if (call.callId && call.callId !== "pending") {
|
|
45
|
+
handlers.setCallId(call.callId);
|
|
46
|
+
}
|
|
47
|
+
}),
|
|
48
|
+
call.on("muteChange", ({ muted }) => {
|
|
49
|
+
handlers.setMuted(muted);
|
|
50
|
+
}),
|
|
51
|
+
call.on("error", ({ code, message, callId }) => {
|
|
52
|
+
handlers.setError({ code, message });
|
|
53
|
+
handlers.setStatus("error");
|
|
54
|
+
if (callId && callId !== "pending") handlers.setCallId(callId);
|
|
55
|
+
}),
|
|
56
|
+
call.on("ended", ({ callId }) => {
|
|
57
|
+
handlers.setStatus("ended");
|
|
58
|
+
if (callId && callId !== "pending") handlers.setCallId(callId);
|
|
59
|
+
})
|
|
60
|
+
];
|
|
61
|
+
return () => {
|
|
62
|
+
offs.forEach((off) => off());
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
var CallEmbedProvider = defineComponent({
|
|
66
|
+
name: "CallEmbedProvider",
|
|
67
|
+
props: {
|
|
68
|
+
publishableKey: { type: String, required: true },
|
|
69
|
+
apiBaseUrl: { type: String, required: true },
|
|
70
|
+
locale: { type: String, default: void 0 },
|
|
71
|
+
copy: {
|
|
72
|
+
type: Object,
|
|
73
|
+
default: void 0
|
|
74
|
+
},
|
|
75
|
+
branding: { type: Boolean, default: void 0 },
|
|
76
|
+
debug: { type: Boolean, default: void 0 },
|
|
77
|
+
queue: { type: String, default: void 0 }
|
|
78
|
+
},
|
|
79
|
+
slots: Object,
|
|
80
|
+
setup(props, { slots }) {
|
|
81
|
+
const status = ref("idle");
|
|
82
|
+
const callId = ref(null);
|
|
83
|
+
const muted = ref(false);
|
|
84
|
+
const error = ref(null);
|
|
85
|
+
const resolvedLocale = ref(props.locale ?? "en");
|
|
86
|
+
const callRef = ref(null);
|
|
87
|
+
let unbind = null;
|
|
88
|
+
const copyKey = computed(() => JSON.stringify(props.copy ?? {}));
|
|
89
|
+
const brandingValue = computed(() => props.branding !== false);
|
|
90
|
+
function hangUpActive() {
|
|
91
|
+
unbind?.();
|
|
92
|
+
unbind = null;
|
|
93
|
+
const call = callRef.value ?? CallEmbed.getActiveCall();
|
|
94
|
+
callRef.value = null;
|
|
95
|
+
if (call && isActiveStatus(call.status)) {
|
|
96
|
+
void call.hangUp();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function runInit() {
|
|
100
|
+
if (typeof window === "undefined") return;
|
|
101
|
+
try {
|
|
102
|
+
CallEmbed.init({
|
|
103
|
+
publishableKey: props.publishableKey,
|
|
104
|
+
apiBaseUrl: props.apiBaseUrl,
|
|
105
|
+
locale: props.locale,
|
|
106
|
+
copy: props.copy,
|
|
107
|
+
branding: props.branding,
|
|
108
|
+
debug: props.debug
|
|
109
|
+
});
|
|
110
|
+
const runtime = CallEmbed._getRuntime();
|
|
111
|
+
if (runtime) resolvedLocale.value = runtime.locale;
|
|
112
|
+
} catch (err) {
|
|
113
|
+
const state = toErrorState(err);
|
|
114
|
+
error.value = state;
|
|
115
|
+
status.value = "error";
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
watch(
|
|
119
|
+
() => [
|
|
120
|
+
props.publishableKey,
|
|
121
|
+
props.apiBaseUrl,
|
|
122
|
+
props.locale,
|
|
123
|
+
copyKey.value,
|
|
124
|
+
brandingValue.value,
|
|
125
|
+
props.debug
|
|
126
|
+
],
|
|
127
|
+
() => {
|
|
128
|
+
runInit();
|
|
129
|
+
},
|
|
130
|
+
{ immediate: true }
|
|
131
|
+
);
|
|
132
|
+
watch(
|
|
133
|
+
() => [props.publishableKey, props.apiBaseUrl],
|
|
134
|
+
(_next, _prev, onCleanup) => {
|
|
135
|
+
onCleanup(() => {
|
|
136
|
+
hangUpActive();
|
|
137
|
+
});
|
|
138
|
+
},
|
|
139
|
+
{ immediate: true }
|
|
140
|
+
);
|
|
141
|
+
async function start(options = {}) {
|
|
142
|
+
try {
|
|
143
|
+
const q = options.queue ?? props.queue;
|
|
144
|
+
if (!q?.trim()) {
|
|
145
|
+
throw new CallEmbedError(
|
|
146
|
+
"invalid_queue",
|
|
147
|
+
"queue is required (pass queue on the provider, button, or start())."
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
error.value = null;
|
|
151
|
+
muted.value = false;
|
|
152
|
+
const userOn = options.on;
|
|
153
|
+
const call = await CallEmbed.startCall({
|
|
154
|
+
...options,
|
|
155
|
+
queue: q,
|
|
156
|
+
hidePanel: true,
|
|
157
|
+
on: {
|
|
158
|
+
...userOn,
|
|
159
|
+
statusChange: (payload) => {
|
|
160
|
+
status.value = payload.status;
|
|
161
|
+
userOn?.statusChange?.(payload);
|
|
162
|
+
},
|
|
163
|
+
muteChange: (payload) => {
|
|
164
|
+
muted.value = payload.muted;
|
|
165
|
+
userOn?.muteChange?.(payload);
|
|
166
|
+
},
|
|
167
|
+
error: (payload) => {
|
|
168
|
+
error.value = { code: payload.code, message: payload.message };
|
|
169
|
+
status.value = "error";
|
|
170
|
+
if (payload.callId && payload.callId !== "pending") {
|
|
171
|
+
callId.value = payload.callId;
|
|
172
|
+
}
|
|
173
|
+
userOn?.error?.(payload);
|
|
174
|
+
},
|
|
175
|
+
ended: (payload) => {
|
|
176
|
+
status.value = "ended";
|
|
177
|
+
if (payload.callId && payload.callId !== "pending") {
|
|
178
|
+
callId.value = payload.callId;
|
|
179
|
+
}
|
|
180
|
+
userOn?.ended?.(payload);
|
|
181
|
+
},
|
|
182
|
+
ringing: (payload) => {
|
|
183
|
+
callId.value = payload.callId;
|
|
184
|
+
userOn?.ringing?.(payload);
|
|
185
|
+
},
|
|
186
|
+
answered: (payload) => {
|
|
187
|
+
callId.value = payload.callId;
|
|
188
|
+
userOn?.answered?.(payload);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
unbind?.();
|
|
193
|
+
callRef.value = call;
|
|
194
|
+
status.value = call.status;
|
|
195
|
+
if (call.callId !== "pending") callId.value = call.callId;
|
|
196
|
+
unbind = bindCall(call, {
|
|
197
|
+
setStatus: (s) => {
|
|
198
|
+
status.value = s;
|
|
199
|
+
},
|
|
200
|
+
setCallId: (id) => {
|
|
201
|
+
callId.value = id;
|
|
202
|
+
},
|
|
203
|
+
setMuted: (m) => {
|
|
204
|
+
muted.value = m;
|
|
205
|
+
},
|
|
206
|
+
setError: (e) => {
|
|
207
|
+
error.value = e;
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
return call;
|
|
211
|
+
} catch (err) {
|
|
212
|
+
const state = toErrorState(err);
|
|
213
|
+
error.value = state;
|
|
214
|
+
status.value = "error";
|
|
215
|
+
if (err instanceof CallEmbedError) throw err;
|
|
216
|
+
throw new CallEmbedError("call_failed", state.message);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
async function end() {
|
|
220
|
+
const call = callRef.value ?? CallEmbed.getActiveCall();
|
|
221
|
+
if (!call) {
|
|
222
|
+
status.value = "idle";
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
await call.hangUp();
|
|
226
|
+
}
|
|
227
|
+
async function setMuted(next) {
|
|
228
|
+
const call = callRef.value ?? CallEmbed.getActiveCall();
|
|
229
|
+
if (!call) {
|
|
230
|
+
muted.value = next;
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
await call.setMuted(next);
|
|
234
|
+
}
|
|
235
|
+
const api = reactive({
|
|
236
|
+
get status() {
|
|
237
|
+
return status.value;
|
|
238
|
+
},
|
|
239
|
+
get uiState() {
|
|
240
|
+
return toUiState(status.value);
|
|
241
|
+
},
|
|
242
|
+
get callId() {
|
|
243
|
+
return callId.value;
|
|
244
|
+
},
|
|
245
|
+
get muted() {
|
|
246
|
+
return muted.value;
|
|
247
|
+
},
|
|
248
|
+
get error() {
|
|
249
|
+
return error.value;
|
|
250
|
+
},
|
|
251
|
+
get locale() {
|
|
252
|
+
return resolvedLocale.value;
|
|
253
|
+
},
|
|
254
|
+
start,
|
|
255
|
+
end,
|
|
256
|
+
setMuted,
|
|
257
|
+
get defaultQueue() {
|
|
258
|
+
return props.queue;
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
provide(CALL_EMBED_KEY, api);
|
|
262
|
+
return () => slots.default?.();
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
function useCallEmbed() {
|
|
266
|
+
const ctx = inject(CALL_EMBED_KEY, null);
|
|
267
|
+
if (!ctx) {
|
|
268
|
+
throw new Error("useCallEmbed() must be used within <CallEmbedProvider>.");
|
|
269
|
+
}
|
|
270
|
+
return ctx;
|
|
271
|
+
}
|
|
272
|
+
function statusLabel(copy, uiState, sdkStatus) {
|
|
273
|
+
switch (uiState) {
|
|
274
|
+
case "idle":
|
|
275
|
+
return copy.ready;
|
|
276
|
+
case "ringing":
|
|
277
|
+
return sdkStatus === "connecting" ? copy.connecting : copy.ringing;
|
|
278
|
+
case "connected":
|
|
279
|
+
return copy.answered;
|
|
280
|
+
case "ended":
|
|
281
|
+
return copy.ended;
|
|
282
|
+
case "error":
|
|
283
|
+
return copy.error;
|
|
284
|
+
default:
|
|
285
|
+
return copy.ready;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
function runtimeForCopy(locale, copyOverrides = {}) {
|
|
289
|
+
return {
|
|
290
|
+
publishableKey: "",
|
|
291
|
+
apiBaseUrl: "",
|
|
292
|
+
locale,
|
|
293
|
+
copyOverrides,
|
|
294
|
+
branding: true,
|
|
295
|
+
debug: false
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// src/CallEmbedButton.ts
|
|
300
|
+
var CallEmbedButton = defineComponent({
|
|
301
|
+
name: "CallEmbedButton",
|
|
302
|
+
props: {
|
|
303
|
+
/** Queue to ring. Falls back to `CallEmbedProvider` `queue`. */
|
|
304
|
+
queue: { type: String, default: void 0 },
|
|
305
|
+
/** Idle-state label; defaults to locale `launchDefault`. */
|
|
306
|
+
label: { type: String, default: void 0 },
|
|
307
|
+
/** Optional metadata forwarded to `startCall`. */
|
|
308
|
+
metadata: {
|
|
309
|
+
type: Object,
|
|
310
|
+
default: void 0
|
|
311
|
+
},
|
|
312
|
+
/** Optional caller display name. */
|
|
313
|
+
displayName: { type: String, default: void 0 },
|
|
314
|
+
/** Show a status line under the button. Default: `true`. */
|
|
315
|
+
showStatus: { type: Boolean, default: true },
|
|
316
|
+
/** Show mute control while ringing/connected. Default: `true`. */
|
|
317
|
+
showMute: { type: Boolean, default: true },
|
|
318
|
+
disabled: { type: Boolean, default: false }
|
|
319
|
+
},
|
|
320
|
+
emits: {
|
|
321
|
+
error: (_error) => true
|
|
322
|
+
},
|
|
323
|
+
setup(props, { emit, attrs }) {
|
|
324
|
+
const embed = useCallEmbed();
|
|
325
|
+
const busy = ref(false);
|
|
326
|
+
const copy = computed(() => resolveCopy(runtimeForCopy(embed.locale)));
|
|
327
|
+
const inCall = computed(
|
|
328
|
+
() => embed.uiState === "ringing" || embed.uiState === "connected"
|
|
329
|
+
);
|
|
330
|
+
const buttonLabel = computed(
|
|
331
|
+
() => inCall.value ? copy.value.hangup : props.label ?? copy.value.launchDefault
|
|
332
|
+
);
|
|
333
|
+
const statusText = computed(() => {
|
|
334
|
+
if (embed.uiState === "error" && embed.error) {
|
|
335
|
+
return friendlyErrorMessage(
|
|
336
|
+
copy.value,
|
|
337
|
+
embed.error.code,
|
|
338
|
+
embed.error.message
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
return statusLabel(copy.value, embed.uiState, embed.status);
|
|
342
|
+
});
|
|
343
|
+
const tone = computed(
|
|
344
|
+
() => embed.uiState === "error" ? "error" : embed.uiState === "connected" ? "ok" : void 0
|
|
345
|
+
);
|
|
346
|
+
async function onClick() {
|
|
347
|
+
if (busy.value) return;
|
|
348
|
+
busy.value = true;
|
|
349
|
+
try {
|
|
350
|
+
if (inCall.value) {
|
|
351
|
+
await embed.end();
|
|
352
|
+
} else {
|
|
353
|
+
await embed.start({
|
|
354
|
+
queue: props.queue ?? embed.defaultQueue,
|
|
355
|
+
metadata: props.metadata,
|
|
356
|
+
displayName: props.displayName
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
} catch (err) {
|
|
360
|
+
const ce = err instanceof CallEmbedError ? err : new CallEmbedError(
|
|
361
|
+
"call_failed",
|
|
362
|
+
err instanceof Error ? err.message : String(err)
|
|
363
|
+
);
|
|
364
|
+
emit("error", ce);
|
|
365
|
+
} finally {
|
|
366
|
+
busy.value = false;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
async function onMuteClick() {
|
|
370
|
+
if (busy.value) return;
|
|
371
|
+
busy.value = true;
|
|
372
|
+
try {
|
|
373
|
+
await embed.setMuted(!embed.muted);
|
|
374
|
+
} catch (err) {
|
|
375
|
+
const ce = err instanceof CallEmbedError ? err : new CallEmbedError(
|
|
376
|
+
"call_failed",
|
|
377
|
+
err instanceof Error ? err.message : String(err)
|
|
378
|
+
);
|
|
379
|
+
emit("error", ce);
|
|
380
|
+
} finally {
|
|
381
|
+
busy.value = false;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
return () => {
|
|
385
|
+
const rootClass = ["ce-vue-root", attrs.class].filter(Boolean).join(" ");
|
|
386
|
+
const children = [
|
|
387
|
+
h(
|
|
388
|
+
"button",
|
|
389
|
+
{
|
|
390
|
+
type: "button",
|
|
391
|
+
class: "ce-vue-button",
|
|
392
|
+
"data-state": embed.uiState,
|
|
393
|
+
disabled: props.disabled || busy.value,
|
|
394
|
+
"aria-busy": busy.value || void 0,
|
|
395
|
+
onClick: () => {
|
|
396
|
+
void onClick();
|
|
397
|
+
}
|
|
398
|
+
},
|
|
399
|
+
buttonLabel.value
|
|
400
|
+
)
|
|
401
|
+
];
|
|
402
|
+
if (props.showMute && inCall.value) {
|
|
403
|
+
children.push(
|
|
404
|
+
h(
|
|
405
|
+
"button",
|
|
406
|
+
{
|
|
407
|
+
type: "button",
|
|
408
|
+
class: "ce-vue-mute",
|
|
409
|
+
disabled: busy.value,
|
|
410
|
+
onClick: () => {
|
|
411
|
+
void onMuteClick();
|
|
412
|
+
}
|
|
413
|
+
},
|
|
414
|
+
embed.muted ? copy.value.unmute : copy.value.mute
|
|
415
|
+
)
|
|
416
|
+
);
|
|
417
|
+
}
|
|
418
|
+
if (props.showStatus) {
|
|
419
|
+
children.push(
|
|
420
|
+
h(
|
|
421
|
+
"p",
|
|
422
|
+
{
|
|
423
|
+
class: "ce-vue-status",
|
|
424
|
+
"data-tone": tone.value,
|
|
425
|
+
"data-state": embed.uiState
|
|
426
|
+
},
|
|
427
|
+
statusText.value
|
|
428
|
+
)
|
|
429
|
+
);
|
|
430
|
+
}
|
|
431
|
+
return h("div", { class: rootClass, "data-ce-vue": "" }, children);
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
// src/plugin.ts
|
|
437
|
+
var CallEmbedPlugin = {
|
|
438
|
+
install(app, options = {}) {
|
|
439
|
+
app.component(options.providerName ?? "CallEmbedProvider", CallEmbedProvider);
|
|
440
|
+
app.component(options.buttonName ?? "CallEmbedButton", CallEmbedButton);
|
|
441
|
+
}
|
|
442
|
+
};
|
|
443
|
+
|
|
444
|
+
export { CALL_EMBED_KEY, CallEmbedButton, CallEmbedPlugin, CallEmbedProvider, statusLabel, toUiState, useCallEmbed };
|
package/dist/styles.css
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default styles for `@callembed/vue`.
|
|
3
|
+
* Theme via `--ce-*` (same public tokens as `@callembed/sdk/ui`).
|
|
4
|
+
*/
|
|
5
|
+
:where(.ce-vue-button, .ce-vue-status, .ce-vue-mute) {
|
|
6
|
+
font-family: var(
|
|
7
|
+
--ce-font,
|
|
8
|
+
"Noto Sans TC",
|
|
9
|
+
"IBM Plex Sans",
|
|
10
|
+
"Segoe UI",
|
|
11
|
+
sans-serif
|
|
12
|
+
);
|
|
13
|
+
color: var(--ce-fg, #e8eef4);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.ce-vue-root {
|
|
17
|
+
display: inline-flex;
|
|
18
|
+
flex-direction: column;
|
|
19
|
+
align-items: flex-start;
|
|
20
|
+
gap: 0.5rem;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.ce-vue-button {
|
|
24
|
+
appearance: none;
|
|
25
|
+
display: inline-block;
|
|
26
|
+
border: 1px solid var(--ce-border, #2a3a46);
|
|
27
|
+
border-radius: var(--ce-radius, 0);
|
|
28
|
+
background: color-mix(in srgb, var(--ce-accent, #5eb0d8) 25%, transparent);
|
|
29
|
+
color: var(--ce-fg, #e8eef4);
|
|
30
|
+
padding: 0.7rem 1.1rem;
|
|
31
|
+
font-size: inherit;
|
|
32
|
+
cursor: pointer;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.ce-vue-button:hover {
|
|
36
|
+
border-color: var(--ce-accent, #5eb0d8);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.ce-vue-button:disabled {
|
|
40
|
+
opacity: 0.5;
|
|
41
|
+
cursor: not-allowed;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.ce-vue-button[data-state="ringing"],
|
|
45
|
+
.ce-vue-button[data-state="connected"] {
|
|
46
|
+
border-color: color-mix(
|
|
47
|
+
in srgb,
|
|
48
|
+
var(--ce-danger, #c44b4b) 55%,
|
|
49
|
+
var(--ce-border, #2a3a46)
|
|
50
|
+
);
|
|
51
|
+
color: var(--ce-error, #f0c4c4);
|
|
52
|
+
background: transparent;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.ce-vue-status {
|
|
56
|
+
margin: 0;
|
|
57
|
+
color: var(--ce-muted, #9aadb8);
|
|
58
|
+
font-size: 0.9rem;
|
|
59
|
+
line-height: 1.4;
|
|
60
|
+
min-height: 1.25em;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.ce-vue-status[data-tone="error"] {
|
|
64
|
+
color: var(--ce-error, #f0c4c4);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.ce-vue-status[data-tone="ok"] {
|
|
68
|
+
color: var(--ce-ok, #9fd6c0);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.ce-vue-mute {
|
|
72
|
+
appearance: none;
|
|
73
|
+
border: 1px solid var(--ce-border, #2a3a46);
|
|
74
|
+
border-radius: var(--ce-radius, 0);
|
|
75
|
+
background: transparent;
|
|
76
|
+
color: inherit;
|
|
77
|
+
padding: 0.45rem 0.75rem;
|
|
78
|
+
font: inherit;
|
|
79
|
+
cursor: pointer;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.ce-vue-mute:hover {
|
|
83
|
+
border-color: var(--ce-accent, #5eb0d8);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.ce-vue-mute:disabled {
|
|
87
|
+
opacity: 0.5;
|
|
88
|
+
cursor: not-allowed;
|
|
89
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,82 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@callembed/vue",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "Vue 3 components and composables for CallEmbed (thin wrapper over @callembed/sdk)",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Sealby",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "./dist/index.cjs",
|
|
9
|
+
"module": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js",
|
|
15
|
+
"require": "./dist/index.cjs",
|
|
16
|
+
"default": "./dist/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./styles.css": "./dist/styles.css",
|
|
19
|
+
"./package.json": "./package.json"
|
|
20
|
+
},
|
|
21
|
+
"sideEffects": [
|
|
22
|
+
"./dist/styles.css"
|
|
23
|
+
],
|
|
24
|
+
"files": [
|
|
25
|
+
"dist",
|
|
26
|
+
"README.md",
|
|
27
|
+
"LICENSE"
|
|
28
|
+
],
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsup && node ./scripts/copy-css.mjs",
|
|
31
|
+
"prepack": "npm run build",
|
|
32
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
33
|
+
"dev": "tsup --watch",
|
|
34
|
+
"test": "vitest run",
|
|
35
|
+
"test:watch": "vitest",
|
|
36
|
+
"pack:verify": "node ./scripts/pack-verify.mjs"
|
|
37
|
+
},
|
|
38
|
+
"homepage": "https://callembed.sealby.me",
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "git+https://github.com/TonyFeng1203/CallEmbed.git",
|
|
42
|
+
"directory": "packages/vue"
|
|
43
|
+
},
|
|
44
|
+
"bugs": {
|
|
45
|
+
"url": "https://github.com/TonyFeng1203/CallEmbed/issues"
|
|
46
|
+
},
|
|
47
|
+
"keywords": [
|
|
48
|
+
"callembed",
|
|
49
|
+
"vue",
|
|
50
|
+
"nuxt",
|
|
51
|
+
"voice",
|
|
52
|
+
"webrtc",
|
|
53
|
+
"livekit",
|
|
54
|
+
"customer-support"
|
|
55
|
+
],
|
|
56
|
+
"engines": {
|
|
57
|
+
"node": ">=20"
|
|
58
|
+
},
|
|
59
|
+
"publishConfig": {
|
|
60
|
+
"access": "public"
|
|
61
|
+
},
|
|
62
|
+
"peerDependencies": {
|
|
63
|
+
"@callembed/sdk": "^0.1.2",
|
|
64
|
+
"livekit-client": "^2.13.0",
|
|
65
|
+
"vue": "^3.4.0"
|
|
66
|
+
},
|
|
67
|
+
"peerDependenciesMeta": {
|
|
68
|
+
"livekit-client": {
|
|
69
|
+
"optional": true
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
"devDependencies": {
|
|
73
|
+
"@callembed/sdk": "^0.1.2",
|
|
74
|
+
"@vue/test-utils": "^2.4.6",
|
|
75
|
+
"jsdom": "26.1.0",
|
|
76
|
+
"livekit-client": "^2.13.0",
|
|
77
|
+
"tsup": "^8.4.0",
|
|
78
|
+
"typescript": "^5.8.3",
|
|
79
|
+
"vitest": "3.2.7",
|
|
80
|
+
"vue": "^3.5.13"
|
|
81
|
+
}
|
|
82
|
+
}
|