Skip to content

Commit ee2cd2e

Browse files
authored
fix(vue-js): support destructuring properly (#434)
1 parent 559c040 commit ee2cd2e

File tree

5 files changed

+64
-39
lines changed

5 files changed

+64
-39
lines changed

packages/vue-sdk/README.md

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,18 @@ If using Nuxt, wrap `<BucketProvider>` in `<ClientOnly>`. `<BucketProvider>` onl
4040
<script setup lang="ts">
4141
import { useFeature } from "@bucketco/vue-sdk";
4242
43-
const huddle = useFeature("huddle");
43+
const { isEnabled } = useFeature("huddle");
4444
</script>
4545
4646
<template>
47-
<div v-if="huddle.isEnabled">
48-
<button @click="huddle.track()">Start huddle!</button>
47+
<div v-if="isEnabled">
48+
<button>Start huddle!</button>
49+
</div>
4950
</template>
5051
```
5152

53+
See [useFeature()](#usefeature) for a full example
54+
5255
## Setting `user` and `company`
5356

5457
Bucket determines which features are active for a given `user`, `company`, or `otherContext`.
@@ -70,7 +73,9 @@ A number of special attributes exist:
7073
:publishable-key="publishableKey"
7174
:user="{ id: 'user_123', name: 'John Doe', email: 'john@acme.com' }"
7275
:company="{ id: 'acme_inc', plan: 'pro' }"
73-
></BucketProvider>
76+
>
77+
<!-- your app -->
78+
</BucketProvider>
7479
```
7580

7681
To retrieve features along with their targeting information, use `useFeature(key: string)` hook (described in a section below).
@@ -149,26 +154,40 @@ If you want more control over loading screens, `useIsLoading()` returns a Ref<bo
149154

150155
### `useFeature()`
151156

152-
Returns the state of a given feature for the current context. The composable provides type-safe access to feature flags and their configurations.
157+
Returns the state of a given feature for the current context. The composable provides access to feature flags and their configurations.
158+
159+
`useFeature()` returns an object with this shape:
160+
161+
```ts
162+
{
163+
isEnabled: boolean, // is the feature enabled
164+
track: () => void, // send a track event when the feature is used
165+
requestFeedback: (...) => void // open up a feedback dialog
166+
config: {key: string, payload: any}, // remote configuration for this feature
167+
isLoading: boolean // if you want to manage loading state at the feature level
168+
}
169+
```
170+
171+
Example:
153172

154173
```vue
155174
<script setup lang="ts">
156175
import { useFeature } from "@bucketco/vue-sdk";
157176
158-
const huddle = useFeature("huddle");
177+
const { isEnabled, track, requestFeedback, config } = useFeature("huddle");
159178
</script>
160179
161180
<template>
162-
<div v-if="huddle.isLoading">Loading...</div>
163-
<div v-else-if="!huddle.isEnabled">Feature not available</div>
181+
<div v-if="isLoading">Loading...</div>
182+
<div v-else-if="!isEnabled">Feature not available</div>
164183
<div v-else>
165-
<button @click="huddle.track()">Start huddle!</button>
184+
<button @click="track()">Start huddle!</button>
166185
<button
167186
@click="
168187
(e) =>
169-
huddle.requestFeedback({
188+
requestFeedback({
170189
title:
171-
huddle.config.payload?.question ??
190+
config.payload?.question ??
172191
'How do you like the Huddles feature?',
173192
position: {
174193
type: 'POPOVER',
@@ -187,7 +206,9 @@ See the reference docs for details.
187206

188207
### `useTrack()`
189208

190-
`useTrack()` lets you send custom events to Bucket. Use this whenever a user _uses_ a feature.
209+
`useTrack()` returns a function which lets you send custom events to Bucket. It takes a string argument with the event name and optionally an object with properties to attach the event.
210+
211+
Using `track` returned from `useFeature()` calles this track function with the feature key as the event name.
191212

192213
```vue
193214
<script setup lang="ts">

packages/vue-sdk/dev/plain/components/StartHuddleButton.vue

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,25 @@ import { useFeature } from "../../../src";
33
44
import Section from "./Section.vue";
55
6-
const huddle = useFeature("huddle");
6+
const { isLoading, isEnabled, config, requestFeedback, track } =
7+
useFeature("huddle");
78
</script>
89
<template>
910
<Section title="Huddle">
1011
<div style="display: flex; gap: 10px; flex-wrap: wrap">
11-
<div>Huddle enabled: {{ huddle.isEnabled }}</div>
12-
<div v-if="huddle.isLoading">Loading...</div>
12+
<div>Huddle enabled: {{ isEnabled }}</div>
13+
<div v-if="isLoading">Loading...</div>
1314
<div v-else style="display: flex; gap: 10px; flex-wrap: wrap">
1415
<div>
15-
<button @click="huddle.track()">
16-
{{
17-
huddle.config.payload?.buttonTitle ?? "Start Huddle (track event)"
18-
}}
16+
<button @click="track()">
17+
{{ config?.payload?.buttonTitle ?? "Start Huddle (track event)" }}
1918
</button>
2019
</div>
2120
<div>
2221
<button
2322
@click="
2423
(e) =>
25-
huddle.requestFeedback({
24+
requestFeedback({
2625
title: 'Do you like huddles?',
2726
})
2827
"

packages/vue-sdk/src/hooks.ts

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,45 @@
1-
import { inject, InjectionKey, onBeforeUnmount, ref } from "vue";
1+
import { computed, inject, InjectionKey, onBeforeUnmount, ref } from "vue";
22

33
import { RequestFeedbackData, UnassignedFeedback } from "@bucketco/browser-sdk";
44

55
import {
6-
FeatureKey,
6+
Feature,
77
ProviderContextType,
88
RequestFeatureFeedbackOptions,
99
} from "./types";
1010

1111
export const ProviderSymbol: InjectionKey<ProviderContextType> =
1212
Symbol("BucketProvider");
1313

14-
export function useFeature<TKey extends FeatureKey>(key: TKey) {
14+
export function useFeature(key: string): Feature<any> {
1515
const client = useClient();
1616
const ctx = injectSafe();
1717

1818
const track = () => client?.value.track(key);
1919
const requestFeedback = (opts: RequestFeatureFeedbackOptions) =>
2020
client.value.requestFeedback({ ...opts, featureKey: key });
2121

22-
function getFeature() {
23-
const f = client.value.getFeature(key);
24-
return {
25-
isEnabled: f.isEnabled,
26-
config: f.config,
27-
track,
28-
requestFeedback,
29-
key,
30-
isLoading: ctx.isLoading,
31-
};
32-
}
22+
const feature = ref(client.value.getFeature(key));
3323

34-
const feature = ref(getFeature());
24+
updateFeature();
3525

3626
function updateFeature() {
37-
feature.value = getFeature();
27+
feature.value = client.value.getFeature(key);
3828
}
3929

4030
client.value.on("featuresUpdated", updateFeature);
4131
onBeforeUnmount(() => {
4232
client.value.off("featuresUpdated", updateFeature);
4333
});
4434

45-
return feature;
35+
return {
36+
key,
37+
isEnabled: computed(() => feature.value.isEnabled),
38+
config: computed(() => feature.value.config),
39+
track,
40+
requestFeedback,
41+
isLoading: computed(() => ctx.isLoading.value),
42+
};
4643
}
4744

4845
/**

packages/vue-sdk/src/index.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@ import {
99
} from "@bucketco/browser-sdk";
1010

1111
import BucketProvider from "./BucketProvider.vue";
12-
import { BucketProps } from "./types";
12+
import {
13+
BucketProps,
14+
EmptyFeatureRemoteConfig,
15+
Feature,
16+
FeatureType,
17+
} from "./types";
1318

1419
export {
1520
useClient,
@@ -29,6 +34,9 @@ export { BucketProvider };
2934
export type {
3035
CheckEvent,
3136
CompanyContext,
37+
EmptyFeatureRemoteConfig,
38+
Feature,
39+
FeatureType,
3240
RawFeatures,
3341
TrackEvent,
3442
UserContext,

packages/vue-sdk/src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export interface Feature<
2828
key: string;
2929
isEnabled: Ref<boolean>;
3030
isLoading: Ref<boolean>;
31-
config: ({ key: string } & TConfig) | EmptyFeatureRemoteConfig;
31+
config: Ref<({ key: string } & TConfig) | EmptyFeatureRemoteConfig>;
3232
track(): Promise<Response | undefined> | undefined;
3333
requestFeedback: (opts: RequestFeatureFeedbackOptions) => void;
3434
}

0 commit comments

Comments
 (0)