@sbc-connect/nuxt-base 0.0.0-test-ld-20260520212549
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/.env.example +11 -0
- package/CHANGELOG.md +338 -0
- package/LICENSE +28 -0
- package/README.md +55 -0
- package/app/app.config.ts +441 -0
- package/app/app.vue +18 -0
- package/app/assets/css/connect-base-layout.css +13 -0
- package/app/assets/css/connect-base-tw.css +303 -0
- package/app/components/Connect/Address/Display.vue +84 -0
- package/app/components/Connect/BCGovLogo.vue +42 -0
- package/app/components/Connect/Breadcrumb.vue +68 -0
- package/app/components/Connect/ButtonControl/Buttons.vue +28 -0
- package/app/components/Connect/ButtonControl/Index.vue +66 -0
- package/app/components/Connect/ButtonControl/Wrapper.vue +18 -0
- package/app/components/Connect/Contact/Display.vue +65 -0
- package/app/components/Connect/FloatingLabel.vue +67 -0
- package/app/components/Connect/Footer.vue +99 -0
- package/app/components/Connect/Header/LogoHomeLink.vue +20 -0
- package/app/components/Connect/Header/WhatsNew.vue +36 -0
- package/app/components/Connect/Header/Wrapper.vue +14 -0
- package/app/components/Connect/Header/index.vue +17 -0
- package/app/components/Connect/I18n/Helper.vue +40 -0
- package/app/components/Connect/Input.vue +69 -0
- package/app/components/Connect/InputDate.vue +104 -0
- package/app/components/Connect/Layout/Index.vue +25 -0
- package/app/components/Connect/Layout/Sidebar.vue +38 -0
- package/app/components/Connect/LocaleSelect.vue +37 -0
- package/app/components/Connect/Modal/Error.vue +76 -0
- package/app/components/Connect/Modal/index.vue +51 -0
- package/app/components/Connect/PageSection.vue +57 -0
- package/app/components/Connect/Select.vue +28 -0
- package/app/components/Connect/Slideover/WhatsNew.vue +61 -0
- package/app/components/Connect/Spinner.vue +91 -0
- package/app/components/Connect/SystemBanner.vue +53 -0
- package/app/components/Connect/Textarea.vue +27 -0
- package/app/components/Connect/Tombstone/Item.vue +51 -0
- package/app/components/Connect/Tombstone/index.vue +123 -0
- package/app/components/Connect/Transition/Collapse.vue +39 -0
- package/app/components/Connect/Transition/Fade.vue +31 -0
- package/app/components/HelloWorld/Index.vue +14 -0
- package/app/composables/useConnectButtonControl.ts +146 -0
- package/app/composables/useConnectLaunchDarkly.ts +173 -0
- package/app/composables/useConnectModal.ts +13 -0
- package/app/composables/useConnectTombstone.ts +25 -0
- package/app/coverage/app/app.config.ts.html +1408 -0
- package/app/coverage/app/app.vue.html +139 -0
- package/app/coverage/app/components/Connect/Address/Display.vue.html +337 -0
- package/app/coverage/app/components/Connect/Address/index.html +116 -0
- package/app/coverage/app/components/Connect/BCGovLogo.vue.html +211 -0
- package/app/coverage/app/components/Connect/Breadcrumb.vue.html +289 -0
- package/app/coverage/app/components/Connect/ButtonControl/Buttons.vue.html +166 -0
- package/app/coverage/app/components/Connect/ButtonControl/Index.vue.html +283 -0
- package/app/coverage/app/components/Connect/ButtonControl/Wrapper.vue.html +139 -0
- package/app/coverage/app/components/Connect/ButtonControl/index.html +146 -0
- package/app/coverage/app/components/Connect/Contact/Display.vue.html +280 -0
- package/app/coverage/app/components/Connect/Contact/index.html +116 -0
- package/app/coverage/app/components/Connect/FloatingLabel.vue.html +286 -0
- package/app/coverage/app/components/Connect/Footer.vue.html +382 -0
- package/app/coverage/app/components/Connect/Header/LogoHomeLink.vue.html +145 -0
- package/app/coverage/app/components/Connect/Header/WhatsNew.vue.html +193 -0
- package/app/coverage/app/components/Connect/Header/Wrapper.vue.html +127 -0
- package/app/coverage/app/components/Connect/Header/index.html +161 -0
- package/app/coverage/app/components/Connect/Header/index.vue.html +136 -0
- package/app/coverage/app/components/Connect/I18n/Helper.vue.html +205 -0
- package/app/coverage/app/components/Connect/I18n/index.html +116 -0
- package/app/coverage/app/components/Connect/Input.vue.html +262 -0
- package/app/coverage/app/components/Connect/InputDate.vue.html +406 -0
- package/app/coverage/app/components/Connect/Layout/Index.vue.html +160 -0
- package/app/coverage/app/components/Connect/Layout/Sidebar.vue.html +199 -0
- package/app/coverage/app/components/Connect/Layout/index.html +131 -0
- package/app/coverage/app/components/Connect/LocaleSelect.vue.html +196 -0
- package/app/coverage/app/components/Connect/Modal/Error.vue.html +313 -0
- package/app/coverage/app/components/Connect/Modal/index.html +131 -0
- package/app/coverage/app/components/Connect/Modal/index.vue.html +238 -0
- package/app/coverage/app/components/Connect/PageSection.vue.html +256 -0
- package/app/coverage/app/components/Connect/Select.vue.html +169 -0
- package/app/coverage/app/components/Connect/Slideover/WhatsNew.vue.html +268 -0
- package/app/coverage/app/components/Connect/Slideover/index.html +116 -0
- package/app/coverage/app/components/Connect/Spinner.vue.html +358 -0
- package/app/coverage/app/components/Connect/SystemBanner.vue.html +244 -0
- package/app/coverage/app/components/Connect/Textarea.vue.html +160 -0
- package/app/coverage/app/components/Connect/Tombstone/Item.vue.html +238 -0
- package/app/coverage/app/components/Connect/Tombstone/index.html +131 -0
- package/app/coverage/app/components/Connect/Tombstone/index.vue.html +454 -0
- package/app/coverage/app/components/Connect/Transition/Collapse.vue.html +202 -0
- package/app/coverage/app/components/Connect/Transition/Fade.vue.html +178 -0
- package/app/coverage/app/components/Connect/Transition/index.html +131 -0
- package/app/coverage/app/components/Connect/index.html +281 -0
- package/app/coverage/app/components/HelloWorld/Index.vue.html +127 -0
- package/app/coverage/app/components/HelloWorld/index.html +116 -0
- package/app/coverage/app/composables/index.html +161 -0
- package/app/coverage/app/composables/useConnectButtonControl.ts.html +523 -0
- package/app/coverage/app/composables/useConnectLaunchDarkly.ts.html +595 -0
- package/app/coverage/app/composables/useConnectModal.ts.html +124 -0
- package/app/coverage/app/composables/useConnectTombstone.ts.html +160 -0
- package/app/coverage/app/error.vue.html +247 -0
- package/app/coverage/app/index.html +146 -0
- package/app/coverage/app/interfaces/connect-address.ts.html +121 -0
- package/app/coverage/app/interfaces/connect-breadcrumb.ts.html +100 -0
- package/app/coverage/app/interfaces/connect-button-control.ts.html +151 -0
- package/app/coverage/app/interfaces/connect-contact-item.ts.html +103 -0
- package/app/coverage/app/interfaces/connect-modal.ts.html +100 -0
- package/app/coverage/app/interfaces/connect-tombstone.ts.html +208 -0
- package/app/coverage/app/interfaces/connect-whatsnew.ts.html +127 -0
- package/app/coverage/app/interfaces/index.html +206 -0
- package/app/coverage/app/layouts/ConnectBase.vue.html +100 -0
- package/app/coverage/app/layouts/index.html +116 -0
- package/app/coverage/app/plugins/index.html +146 -0
- package/app/coverage/app/plugins/maska.client.ts.html +115 -0
- package/app/coverage/app/plugins/sanitize.client.ts.html +151 -0
- package/app/coverage/app/plugins/whats-new.client.ts.html +220 -0
- package/app/coverage/app/types/dates.ts.html +136 -0
- package/app/coverage/app/types/index.html +116 -0
- package/app/coverage/app/utils/appendUrlParam.ts.html +97 -0
- package/app/coverage/app/utils/getErrorMessage.ts.html +211 -0
- package/app/coverage/app/utils/getErrorStatus.ts.html +196 -0
- package/app/coverage/app/utils/index.html +191 -0
- package/app/coverage/app/utils/logFetchError.ts.html +193 -0
- package/app/coverage/app/utils/parseSpecialCharacters.ts.html +160 -0
- package/app/coverage/app/utils/setBreadcrumbs.ts.html +100 -0
- package/app/coverage/base.css +224 -0
- package/app/coverage/block-navigation.js +87 -0
- package/app/coverage/clover.xml +2094 -0
- package/app/coverage/coverage-final.json +58 -0
- package/app/coverage/favicon.png +0 -0
- package/app/coverage/index.html +386 -0
- package/app/coverage/prettify.css +1 -0
- package/app/coverage/prettify.js +2 -0
- package/app/coverage/sort-arrow-sprite.png +0 -0
- package/app/coverage/sorter.js +210 -0
- package/app/error.vue +54 -0
- package/app/interfaces/connect-address.ts +12 -0
- package/app/interfaces/connect-breadcrumb.ts +5 -0
- package/app/interfaces/connect-button-control.ts +23 -0
- package/app/interfaces/connect-contact-item.ts +6 -0
- package/app/interfaces/connect-modal.ts +5 -0
- package/app/interfaces/connect-tombstone.ts +41 -0
- package/app/interfaces/connect-whatsnew.ts +14 -0
- package/app/layouts/ConnectBase.vue +5 -0
- package/app/plugins/maska.client.ts +10 -0
- package/app/plugins/sanitize.client.ts +22 -0
- package/app/plugins/whats-new.client.ts +45 -0
- package/app/spa-loading-template.html +61 -0
- package/app/types/base-app-config.d.ts +15 -0
- package/app/types/base-directives.d.ts +7 -0
- package/app/types/base-page-meta.d.ts +8 -0
- package/app/types/dates.ts +17 -0
- package/app/utils/appendUrlParam.ts +4 -0
- package/app/utils/getErrorMessage.ts +42 -0
- package/app/utils/getErrorStatus.ts +37 -0
- package/app/utils/logFetchError.ts +36 -0
- package/app/utils/parseSpecialCharacters.ts +25 -0
- package/app/utils/setBreadcrumbs.ts +7 -0
- package/firebase.json +34 -0
- package/i18n/locales/en-CA.ts +70 -0
- package/i18n/locales/fr-CA.ts +96 -0
- package/nuxt.config.ts +147 -0
- package/package.json +49 -0
- package/public/BCGovLogo/gov_bc_logo_horiz_en.png +0 -0
- package/public/BCGovLogo/gov_bc_logo_horiz_fr.png +0 -0
- package/public/BCGovLogo/gov_bc_logo_vert_en.png +0 -0
- package/public/BCGovLogo/gov_bc_logo_vert_fr.png +0 -0
- package/public/favicon.ico +0 -0
- package/public/fonts/BCSans/BCSans-Bold.woff +0 -0
- package/public/fonts/BCSans/BCSans-Bold.woff2 +0 -0
- package/public/fonts/BCSans/BCSans-BoldItalic.woff +0 -0
- package/public/fonts/BCSans/BCSans-BoldItalic.woff2 +0 -0
- package/public/fonts/BCSans/BCSans-Italic.woff +0 -0
- package/public/fonts/BCSans/BCSans-Italic.woff2 +0 -0
- package/public/fonts/BCSans/BCSans-Regular.woff +0 -0
- package/public/fonts/BCSans/BCSans-Regular.woff2 +0 -0
- package/public/fonts/BCSans/LICENSE_OFL.txt +94 -0
- package/test-results/.last-run.json +7 -0
- package/test-results/error-page-404-Error-vue-D-1eb51-cted-visuals-with-404-error-Desktop-Chrome/error-context.md +135 -0
- package/test-results/error-page-404-Error-vue-D-1eb51-cted-visuals-with-404-error-Desktop-Chrome/test-failed-1.png +0 -0
- package/test-results/error-page-404-Error-vue-D-1eb51-cted-visuals-with-404-error-Desktop-Chrome/trace.zip +0 -0
- package/test-results/error-page-500-Error-vue-D-8c2cf-cted-visuals-with-500-error-Desktop-Chrome/error-context.md +135 -0
- package/test-results/error-page-500-Error-vue-D-8c2cf-cted-visuals-with-500-error-Desktop-Chrome/test-failed-1.png +0 -0
- package/test-results/error-page-500-Error-vue-D-8c2cf-cted-visuals-with-500-error-Desktop-Chrome/trace.zip +0 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
const defaultOptions: ConnectButtonControlOptions = {
|
|
2
|
+
handleLoading: true,
|
|
3
|
+
clearAlertTextOnClick: true
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export const useConnectButtonControl = (
|
|
7
|
+
stateKey: string = 'default-button-control',
|
|
8
|
+
opts: Partial<ConnectButtonControlOptions> = {}
|
|
9
|
+
) => {
|
|
10
|
+
const options = {
|
|
11
|
+
...defaultOptions,
|
|
12
|
+
...opts
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const buttonControl = useState<ConnectButtonControl>(stateKey, () => ({
|
|
16
|
+
leftGroup: { buttons: [] },
|
|
17
|
+
rightGroup: { buttons: [] }
|
|
18
|
+
}))
|
|
19
|
+
|
|
20
|
+
const forEachButton = (update: (button: ConnectButton, group: 'left' | 'right', index: number) => void) => {
|
|
21
|
+
buttonControl.value.leftGroup?.buttons?.forEach((btn, index) => update(btn, 'left', index))
|
|
22
|
+
buttonControl.value.rightGroup?.buttons?.forEach((btn, index) => update(btn, 'right', index))
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const forEachGroup = (update: (group: ConnectButtonGroup) => void) => {
|
|
26
|
+
if (buttonControl.value.leftGroup) {
|
|
27
|
+
update(buttonControl.value.leftGroup)
|
|
28
|
+
}
|
|
29
|
+
if (buttonControl.value.rightGroup) {
|
|
30
|
+
update(buttonControl.value.rightGroup)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async function setAlertText(text?: string, group?: 'left' | 'right', index?: number) {
|
|
35
|
+
forEachGroup(group => group.alertText = undefined)
|
|
36
|
+
forEachButton(btn => btn.alertText = undefined)
|
|
37
|
+
|
|
38
|
+
if (text && group !== undefined) {
|
|
39
|
+
await nextTick()
|
|
40
|
+
|
|
41
|
+
const buttonGroup = group === 'left' ? buttonControl.value.leftGroup : buttonControl.value.rightGroup
|
|
42
|
+
|
|
43
|
+
if (index !== undefined) {
|
|
44
|
+
const button = buttonGroup.buttons[index]
|
|
45
|
+
if (button) {
|
|
46
|
+
button.alertText = text
|
|
47
|
+
}
|
|
48
|
+
} else {
|
|
49
|
+
buttonGroup.alertText = text
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const handleClick = (
|
|
55
|
+
originalClick: ConnectButton['onClick'],
|
|
56
|
+
group: 'left' | 'right',
|
|
57
|
+
index: number
|
|
58
|
+
) => {
|
|
59
|
+
if (!originalClick || typeof originalClick !== 'function') {
|
|
60
|
+
return undefined
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return async () => {
|
|
64
|
+
try {
|
|
65
|
+
if (options.clearAlertTextOnClick) {
|
|
66
|
+
await setAlertText(undefined)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (options.handleLoading) {
|
|
70
|
+
const clickedButton = buttonControl.value[group === 'left' ? 'leftGroup' : 'rightGroup']?.buttons[index]
|
|
71
|
+
if (!clickedButton) {
|
|
72
|
+
return
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
clickedButton.loading = true
|
|
76
|
+
forEachButton((button, btnGroup, btnIndex) => {
|
|
77
|
+
if (btnGroup !== group || btnIndex !== index) {
|
|
78
|
+
button.disabled = true
|
|
79
|
+
}
|
|
80
|
+
})
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
await (originalClick as () => Promise<void> | void)()
|
|
84
|
+
} catch (error) {
|
|
85
|
+
if (import.meta.env.DEV) {
|
|
86
|
+
console.error(`Error on button click. group: ${group} index: ${index} error: ${error}`)
|
|
87
|
+
}
|
|
88
|
+
} finally {
|
|
89
|
+
if (options.handleLoading) {
|
|
90
|
+
forEachButton((button) => {
|
|
91
|
+
button.loading = false
|
|
92
|
+
button.disabled = false
|
|
93
|
+
})
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function setButtonControl(config: ConnectButtonControl) {
|
|
100
|
+
const updateGroup = (config: { buttons: ConnectButton[] }, group: 'left' | 'right') => {
|
|
101
|
+
if (!config || !config.buttons.length) {
|
|
102
|
+
return { ...config, buttons: [] }
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
...config,
|
|
106
|
+
buttons: config.buttons.map((button, index) => ({
|
|
107
|
+
...button,
|
|
108
|
+
onClick: handleClick(button.onClick, group, index)
|
|
109
|
+
}))
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
buttonControl.value = {
|
|
114
|
+
leftGroup: updateGroup(config.leftGroup, 'left'),
|
|
115
|
+
rightGroup: updateGroup(config.rightGroup, 'right')
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function handleButtonLoading(
|
|
120
|
+
loading: boolean,
|
|
121
|
+
group?: 'left' | 'right',
|
|
122
|
+
index?: number
|
|
123
|
+
) {
|
|
124
|
+
if (!loading) {
|
|
125
|
+
forEachButton((button) => {
|
|
126
|
+
button.loading = false
|
|
127
|
+
button.disabled = false
|
|
128
|
+
})
|
|
129
|
+
} else if (group !== undefined && index !== undefined) {
|
|
130
|
+
forEachButton((button, btnGroup, btnIndex) => {
|
|
131
|
+
if (btnGroup === group && btnIndex === index) {
|
|
132
|
+
button.loading = true
|
|
133
|
+
} else {
|
|
134
|
+
button.disabled = true
|
|
135
|
+
}
|
|
136
|
+
})
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return {
|
|
141
|
+
setButtonControl,
|
|
142
|
+
setAlertText,
|
|
143
|
+
handleButtonLoading,
|
|
144
|
+
buttonControl
|
|
145
|
+
}
|
|
146
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { createClient } from '@launchdarkly/js-client-sdk'
|
|
2
|
+
import type { LDClient, LDFlagSet, LDOptions, LDContext } from '@launchdarkly/js-client-sdk'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Composable for the LaunchDarkly service.
|
|
6
|
+
*/
|
|
7
|
+
export const useConnectLaunchDarkly = () => {
|
|
8
|
+
const ldClient = useState<LDClient | null>('ld-client', () => null)
|
|
9
|
+
const ldFlagSet = useState<LDFlagSet>('ld-flag-set', () => ({}))
|
|
10
|
+
const ldInitialized = useState<boolean>('ld-initialized', () => false)
|
|
11
|
+
const isInitializing = useState<boolean>('ld-is-initializing', () => false)
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Initializes the LaunchDarkly client with an anonymous context.
|
|
15
|
+
*/
|
|
16
|
+
function init(): void {
|
|
17
|
+
const rtc = useRuntimeConfig().public
|
|
18
|
+
|
|
19
|
+
// Prevent re-initialization
|
|
20
|
+
if (ldInitialized.value || isInitializing.value) {
|
|
21
|
+
return
|
|
22
|
+
}
|
|
23
|
+
// Prevent initialization if missing client ID
|
|
24
|
+
if (!rtc.ldClientId) {
|
|
25
|
+
console.error('LaunchDarkly: ldClientId is not configured.')
|
|
26
|
+
return
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
isInitializing.value = true
|
|
30
|
+
|
|
31
|
+
const ldContext: LDContext = {
|
|
32
|
+
kind: 'user',
|
|
33
|
+
key: 'anonymous',
|
|
34
|
+
anonymous: true,
|
|
35
|
+
appSource: rtc.appName
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const options: LDOptions = {
|
|
39
|
+
streaming: false,
|
|
40
|
+
useReport: false,
|
|
41
|
+
diagnosticOptOut: true
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
const client = createClient(rtc.ldClientId, ldContext, options)
|
|
46
|
+
|
|
47
|
+
client.start().then((result) => {
|
|
48
|
+
if (result.status === 'complete') {
|
|
49
|
+
ldFlagSet.value = client.allFlags()
|
|
50
|
+
ldInitialized.value = true
|
|
51
|
+
isInitializing.value = false
|
|
52
|
+
console.info('LaunchDarkly: Anonymous initialization complete.')
|
|
53
|
+
} else {
|
|
54
|
+
console.error('LaunchDarkly: Initialization did not complete.', result)
|
|
55
|
+
isInitializing.value = false
|
|
56
|
+
}
|
|
57
|
+
}).catch((error) => {
|
|
58
|
+
console.error('LaunchDarkly: Initialization error.', error)
|
|
59
|
+
isInitializing.value = false
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
ldClient.value = client
|
|
63
|
+
} catch (error) {
|
|
64
|
+
console.error('LaunchDarkly: Failed to initialize.', error)
|
|
65
|
+
isInitializing.value = false
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Initialize only once on the client
|
|
70
|
+
if (!ldInitialized.value && !isInitializing.value && import.meta.client) {
|
|
71
|
+
init()
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Returns a flag's value. Can operate in two modes.
|
|
76
|
+
* @param name The name of the feature flag.
|
|
77
|
+
* @param defaultValue The value to use until the flag is loaded.
|
|
78
|
+
* @param mode - 'reactive' (default) returns a ref that updates automatically.
|
|
79
|
+
* 'await' returns a promise that resolves when the client is ready.
|
|
80
|
+
* @returns A readonly ref or a promise resolving to the flag's value.
|
|
81
|
+
*/
|
|
82
|
+
function getFeatureFlag<T>(
|
|
83
|
+
name: string,
|
|
84
|
+
defaultValue: T,
|
|
85
|
+
mode: 'await'
|
|
86
|
+
): Promise<T>
|
|
87
|
+
function getFeatureFlag<T>(
|
|
88
|
+
name: string,
|
|
89
|
+
defaultValue?: T,
|
|
90
|
+
mode?: 'reactive'
|
|
91
|
+
): Readonly<Ref<T>>
|
|
92
|
+
function getFeatureFlag<T>(
|
|
93
|
+
name: string,
|
|
94
|
+
defaultValue: T,
|
|
95
|
+
mode: 'reactive' | 'await' = 'reactive'
|
|
96
|
+
): Readonly<Ref<T>> | Promise<T> {
|
|
97
|
+
if (mode === 'await') {
|
|
98
|
+
if (!ldClient.value) {
|
|
99
|
+
return Promise.resolve(defaultValue)
|
|
100
|
+
}
|
|
101
|
+
return ldClient.value.waitForInitialization().then(() =>
|
|
102
|
+
ldClient.value ? ldClient.value.variation(name, defaultValue) : defaultValue
|
|
103
|
+
).catch((error) => {
|
|
104
|
+
console.error(`LaunchDarkly: Error waiting for client while getting flag "${name}".`, error)
|
|
105
|
+
return defaultValue
|
|
106
|
+
})
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// reactive mode
|
|
110
|
+
return readonly(computed(() => {
|
|
111
|
+
if (!ldClient.value || !ldInitialized.value) {
|
|
112
|
+
return defaultValue
|
|
113
|
+
}
|
|
114
|
+
return ldClient.value.variation(name, defaultValue)
|
|
115
|
+
}))
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Returns a flag's value from the locally stored flag set. Can operate in two modes.
|
|
120
|
+
* @param name The name of the feature flag.
|
|
121
|
+
* @param defaultValue The value to use until the flag is loaded.
|
|
122
|
+
* @param mode - 'reactive' (default) returns a ref that updates automatically.
|
|
123
|
+
* 'await' returns a promise that resolves when the client is ready.
|
|
124
|
+
* @returns A readonly ref or a promise resolving to the flag's value.
|
|
125
|
+
*/
|
|
126
|
+
async function getStoredFlag<T>(name: string, defaultValue: T, mode: 'await'): Promise<T>
|
|
127
|
+
function getStoredFlag<T>(name: string, defaultValue?: T, mode?: 'reactive'): Readonly<Ref<T>>
|
|
128
|
+
function getStoredFlag<T>(
|
|
129
|
+
name: string,
|
|
130
|
+
defaultValue: T,
|
|
131
|
+
mode: 'reactive' | 'await' = 'reactive'
|
|
132
|
+
): Readonly<Ref<T>> | Promise<T> {
|
|
133
|
+
if (mode === 'await') {
|
|
134
|
+
if (!ldClient.value) {
|
|
135
|
+
return Promise.resolve(defaultValue)
|
|
136
|
+
}
|
|
137
|
+
return ldClient.value.waitForInitialization().then(() =>
|
|
138
|
+
ldFlagSet.value[name] ?? defaultValue
|
|
139
|
+
).catch((error) => {
|
|
140
|
+
console.error(`LaunchDarkly: Error waiting for client while getting stored flag "${name}".`, error)
|
|
141
|
+
return defaultValue
|
|
142
|
+
})
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// reactive mode
|
|
146
|
+
return readonly(computed(() => {
|
|
147
|
+
if (!ldInitialized.value) {
|
|
148
|
+
return defaultValue
|
|
149
|
+
}
|
|
150
|
+
return ldFlagSet.value[name] ?? defaultValue
|
|
151
|
+
}))
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Resets the LaunchDarkly state and closes the client connection.
|
|
156
|
+
*/
|
|
157
|
+
const $reset = () => {
|
|
158
|
+
ldInitialized.value = false
|
|
159
|
+
isInitializing.value = false
|
|
160
|
+
ldClient.value?.close()
|
|
161
|
+
ldClient.value = null
|
|
162
|
+
ldFlagSet.value = {}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return {
|
|
166
|
+
getFeatureFlag,
|
|
167
|
+
getStoredFlag,
|
|
168
|
+
ldInitialized: readonly(ldInitialized),
|
|
169
|
+
ldFlagSet: readonly(ldFlagSet),
|
|
170
|
+
ldClient: readonly(ldClient),
|
|
171
|
+
$reset
|
|
172
|
+
}
|
|
173
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ConnectModal, ConnectModalError } from '#components'
|
|
2
|
+
|
|
3
|
+
export const useConnectModal = () => {
|
|
4
|
+
const overlay = useOverlay()
|
|
5
|
+
|
|
6
|
+
const baseModal = overlay.create(ConnectModal)
|
|
7
|
+
const errorModal = overlay.create(ConnectModalError)
|
|
8
|
+
|
|
9
|
+
return {
|
|
10
|
+
baseModal,
|
|
11
|
+
errorModal
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export const useConnectTombstone = (
|
|
2
|
+
stateKey: string = 'default-tombstone',
|
|
3
|
+
initialState?: Partial<ConnectTombstoneState>
|
|
4
|
+
) => {
|
|
5
|
+
function createInitialState(): ConnectTombstoneState {
|
|
6
|
+
const baseState: ConnectTombstoneState = {
|
|
7
|
+
loading: false,
|
|
8
|
+
title: {} as ConnectTombstoneTitle,
|
|
9
|
+
subtitles: [],
|
|
10
|
+
details: [],
|
|
11
|
+
sideDetails: [],
|
|
12
|
+
bottomButtons: []
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return { ...baseState, ...initialState }
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const tombstone = useState<ConnectTombstoneState>(stateKey, () => createInitialState())
|
|
19
|
+
|
|
20
|
+
function $reset() {
|
|
21
|
+
tombstone.value = createInitialState()
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return { tombstone, $reset }
|
|
25
|
+
}
|