|
1 | 1 | import { Derived, Effect, Store } from '@tanstack/react-store'
|
2 | 2 |
|
| 3 | +import { getAddOnStatus } from './add-ons' |
| 4 | + |
3 | 5 | import type { Mode, SerializedOptions } from '@tanstack/cta-engine'
|
| 6 | + |
4 | 7 | import type { AddOnInfo, ProjectFiles, StarterInfo } from '@/types.js'
|
5 | 8 |
|
6 | 9 | export const isInitialized = new Store<boolean>(false)
|
@@ -58,8 +61,6 @@ export const availableAddOns = new Derived<Array<AddOnInfo>>({
|
58 | 61 | })
|
59 | 62 | availableAddOns.mount()
|
60 | 63 |
|
61 |
| -export const selectedAddOns = new Store<Array<AddOnInfo>>([]) |
62 |
| - |
63 | 64 | export const modeEditable = new Derived<boolean>({
|
64 | 65 | fn: () => {
|
65 | 66 | return projectStarter.state === undefined
|
@@ -87,6 +88,46 @@ export const tailwindEditable = new Derived<boolean>({
|
87 | 88 | })
|
88 | 89 | tailwindEditable.mount()
|
89 | 90 |
|
| 91 | +export const originalSelectedAddOns = new Store<Array<string>>([]) |
| 92 | +export const userSelectedAddOns = new Store<Array<string>>([]) |
| 93 | + |
| 94 | +export const addOnState = new Derived< |
| 95 | + Record< |
| 96 | + string, |
| 97 | + { |
| 98 | + selected: boolean |
| 99 | + enabled: boolean |
| 100 | + } |
| 101 | + > |
| 102 | +>({ |
| 103 | + fn: () => { |
| 104 | + const originalAddOns: Set<string> = new Set() |
| 105 | + for (const addOn of projectStarter.state?.dependsOn || []) { |
| 106 | + originalAddOns.add(addOn) |
| 107 | + } |
| 108 | + for (const addOn of originalSelectedAddOns.state) { |
| 109 | + originalAddOns.add(addOn) |
| 110 | + } |
| 111 | + |
| 112 | + return getAddOnStatus( |
| 113 | + availableAddOns.state, |
| 114 | + userSelectedAddOns.state, |
| 115 | + originalSelectedAddOns.state, |
| 116 | + ) |
| 117 | + }, |
| 118 | + deps: [availableAddOns, userSelectedAddOns, originalSelectedAddOns], |
| 119 | +}) |
| 120 | +addOnState.mount() |
| 121 | + |
| 122 | +export const selectedAddOns = new Derived<Array<AddOnInfo>>({ |
| 123 | + fn: () => { |
| 124 | + return availableAddOns.state.filter( |
| 125 | + (addOn) => addOnState.state[addOn.id].selected, |
| 126 | + ) |
| 127 | + }, |
| 128 | + deps: [availableAddOns, addOnState], |
| 129 | +}) |
| 130 | + |
90 | 131 | const onProjectChange = new Effect({
|
91 | 132 | fn: async () => {
|
92 | 133 | if (applicationMode.state === 'setup') {
|
@@ -136,6 +177,18 @@ const onProjectChange = new Effect({
|
136 | 177 | })
|
137 | 178 | onProjectChange.mount()
|
138 | 179 |
|
| 180 | +export function toggleAddOn(addOnId: string) { |
| 181 | + if (addOnState.state[addOnId].enabled) { |
| 182 | + if (addOnState.state[addOnId].selected) { |
| 183 | + userSelectedAddOns.setState((state) => |
| 184 | + state.filter((addOn) => addOn !== addOnId), |
| 185 | + ) |
| 186 | + } else { |
| 187 | + userSelectedAddOns.setState((state) => [...state, addOnId]) |
| 188 | + } |
| 189 | + } |
| 190 | +} |
| 191 | + |
139 | 192 | // Application setup
|
140 | 193 |
|
141 | 194 | export const includeFiles = new Store<Array<string>>([
|
@@ -189,6 +242,7 @@ export async function loadInitialSetup() {
|
189 | 242 | output,
|
190 | 243 | }))
|
191 | 244 | projectOptions.setState(() => options)
|
| 245 | + originalSelectedAddOns.setState(() => options.chosenAddOns) |
192 | 246 | projectLocalFiles.setState(() => localFiles)
|
193 | 247 |
|
194 | 248 | isInitialized.setState(() => true)
|
|
0 commit comments