astro-tractstack 2.0.0-rc.5 → 2.0.0-rc.7

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
@@ -283,7 +283,7 @@ sudo ~/t8k/src/tractstack-go/pkg/scripts/t8k-uninstall.sh
283
283
 
284
284
  ## Support & Documentation
285
285
 
286
- - **Documentation**: https://tractstack.org/docs
286
+ - **Documentation**: https://tractstack.org
287
287
  - **GitHub Issues**: https://github.com/AtRiskMedia/tractstack-go/issues
288
288
  - **Email Support**: hello@tractstack.com
289
289
  - **Community**: Join discussions about adaptive web experiences
@@ -29,7 +29,7 @@ function detectPackageManager() {
29
29
  }
30
30
 
31
31
  // Parse existing .env file
32
- function parseExistingEnv() {
32
+ function getEnvState() {
33
33
  const defaults = {
34
34
  goBackend: 'http://localhost:8080',
35
35
  tenantId: 'default',
@@ -37,8 +37,15 @@ function parseExistingEnv() {
37
37
  enableMultiTenant: false,
38
38
  };
39
39
 
40
+ const found = {
41
+ goBackend: false,
42
+ tenantId: false,
43
+ goBackendPath: false,
44
+ enableMultiTenant: false,
45
+ };
46
+
40
47
  if (!existsSync('.env')) {
41
- return defaults;
48
+ return { envDefaults: defaults, envState: found };
42
49
  }
43
50
 
44
51
  try {
@@ -50,7 +57,6 @@ function parseExistingEnv() {
50
57
  if (line && !line.startsWith('#')) {
51
58
  const [key, ...valueParts] = line.split('=');
52
59
  if (key && valueParts.length > 0) {
53
- // Remove surrounding quotes and trim
54
60
  let value = valueParts.join('=').trim();
55
61
  if (
56
62
  (value.startsWith('"') && value.endsWith('"')) ||
@@ -64,18 +70,26 @@ function parseExistingEnv() {
64
70
  });
65
71
 
66
72
  return {
67
- goBackend: envVars.PUBLIC_GO_BACKEND || defaults.goBackend,
68
- tenantId: envVars.PUBLIC_TENANTID || defaults.tenantId,
69
- goBackendPath: envVars.PRIVATE_GO_BACKEND_PATH || defaults.goBackendPath,
70
- enableMultiTenant:
71
- envVars.PUBLIC_ENABLE_MULTI_TENANT === 'true' ||
72
- defaults.enableMultiTenant,
73
+ envDefaults: {
74
+ goBackend: envVars.PUBLIC_GO_BACKEND || defaults.goBackend,
75
+ tenantId: envVars.PUBLIC_TENANTID || defaults.tenantId,
76
+ goBackendPath:
77
+ envVars.PRIVATE_GO_BACKEND_PATH || defaults.goBackendPath,
78
+ enableMultiTenant:
79
+ envVars.ENABLE_MULTI_TENANT === 'true' || defaults.enableMultiTenant,
80
+ },
81
+ envState: {
82
+ goBackend: !!envVars.PUBLIC_GO_BACKEND,
83
+ tenantId: !!envVars.PUBLIC_TENANTID,
84
+ goBackendPath: !!envVars.PRIVATE_GO_BACKEND_PATH,
85
+ enableMultiTenant: !!envVars.ENABLE_MULTI_TENANT,
86
+ },
73
87
  };
74
88
  } catch (error) {
75
89
  console.log(
76
90
  kleur.yellow('⚠️ Found .env file but could not parse it, using defaults')
77
91
  );
78
- return defaults;
92
+ return { envDefaults: defaults, envState: found };
79
93
  }
80
94
  }
81
95
 
@@ -141,7 +155,7 @@ ${kleur.bold('Examples:')}
141
155
  }
142
156
 
143
157
  // Parse existing .env values
144
- const envDefaults = parseExistingEnv();
158
+ const { envDefaults, envState } = getEnvState();
145
159
  const hasExistingEnv = existsSync('.env');
146
160
 
147
161
  if (hasExistingEnv) {
@@ -152,9 +166,11 @@ ${kleur.bold('Examples:')}
152
166
  );
153
167
  }
154
168
 
155
- // Prompt for configuration with existing values as defaults
156
- const responses = await prompts([
157
- {
169
+ // Build prompts array conditionally - only prompt for values not in .env
170
+ const promptQuestions = [];
171
+
172
+ if (!envState.goBackend) {
173
+ promptQuestions.push({
158
174
  type: 'text',
159
175
  name: 'goBackend',
160
176
  message: 'TractStack Go backend URL:',
@@ -167,21 +183,46 @@ ${kleur.bold('Examples:')}
167
183
  return 'Please enter a valid URL';
168
184
  }
169
185
  },
170
- },
171
- {
186
+ });
187
+ } else {
188
+ console.log(
189
+ kleur.green(`✓ Using Go backend URL: ${envDefaults.goBackend}`)
190
+ );
191
+ }
192
+
193
+ if (!envState.enableMultiTenant && !enableMultiTenant) {
194
+ promptQuestions.push({
172
195
  type: 'confirm',
173
196
  name: 'enableMultiTenant',
174
197
  message: 'Enable multi-tenant functionality?',
175
198
  initial: enableMultiTenant || envDefaults.enableMultiTenant,
176
- },
177
- {
178
- type: (prev, values) => (values.enableMultiTenant ? 'text' : null),
199
+ });
200
+ } else {
201
+ const willEnable = enableMultiTenant || envDefaults.enableMultiTenant;
202
+ console.log(
203
+ kleur.green(
204
+ `✓ Multi-tenant functionality: ${willEnable ? 'enabled' : 'disabled'}`
205
+ )
206
+ );
207
+ }
208
+
209
+ // Only prompt for tenantId if multi-tenant will be enabled and tenantId not in .env
210
+ const willEnableMultiTenant =
211
+ enableMultiTenant || envDefaults.enableMultiTenant;
212
+ if (willEnableMultiTenant && !envState.tenantId) {
213
+ promptQuestions.push({
214
+ type: 'text',
179
215
  name: 'tenantId',
180
216
  message: 'Tenant ID:',
181
217
  initial: envDefaults.tenantId,
182
218
  validate: (value) => value.length > 0 || 'Tenant ID is required',
183
- },
184
- {
219
+ });
220
+ } else if (willEnableMultiTenant) {
221
+ console.log(kleur.green(`✓ Using Tenant ID: ${envDefaults.tenantId}`));
222
+ }
223
+
224
+ if (!envState.goBackendPath) {
225
+ promptQuestions.push({
185
226
  type: 'text',
186
227
  name: 'goBackendPath',
187
228
  message: 'TractStack Go backend path:',
@@ -192,37 +233,58 @@ ${kleur.bold('Examples:')}
192
233
  }
193
234
  return true;
194
235
  },
195
- },
196
- {
197
- type: 'confirm',
198
- name: 'includeExamples',
199
- message:
200
- 'Include CodeHook examples? (custom components, collections route)',
201
- initial: includeExamples,
202
- },
203
- ]);
236
+ });
237
+ } else {
238
+ console.log(
239
+ kleur.green(`✓ Using Go backend path: ${envDefaults.goBackendPath}`)
240
+ );
241
+ }
242
+
243
+ // Always ask about examples (not stored in .env)
244
+ promptQuestions.push({
245
+ type: 'confirm',
246
+ name: 'includeExamples',
247
+ message:
248
+ 'Include CodeHook examples? (custom components, collections route)',
249
+ initial: includeExamples,
250
+ });
251
+
252
+ // Run prompts only if there are questions
253
+ const responses =
254
+ promptQuestions.length > 0 ? await prompts(promptQuestions) : {};
255
+
256
+ // Merge responses with env defaults for final values
257
+ const finalResponses = {
258
+ goBackend: responses.goBackend || envDefaults.goBackend,
259
+ enableMultiTenant:
260
+ responses.enableMultiTenant ??
261
+ (enableMultiTenant || envDefaults.enableMultiTenant),
262
+ tenantId: responses.tenantId || envDefaults.tenantId,
263
+ goBackendPath: responses.goBackendPath || envDefaults.goBackendPath,
264
+ includeExamples: responses.includeExamples ?? includeExamples,
265
+ };
204
266
 
205
- if (!responses.goBackend) {
206
- console.log(kleur.red('\n Setup cancelled.'));
267
+ if (!finalResponses.goBackend) {
268
+ console.log(kleur.red('\n Setup cancelled.'));
207
269
  process.exit(1);
208
270
  }
209
271
 
210
272
  // Use existing tenantId if multi-tenant is disabled
211
- const finalTenantId = responses.enableMultiTenant
212
- ? responses.tenantId
273
+ const finalTenantId = finalResponses.enableMultiTenant
274
+ ? finalResponses.tenantId
213
275
  : envDefaults.tenantId;
214
276
 
215
277
  if (!finalTenantId) {
216
- console.log(kleur.red('\n Setup cancelled - Tenant ID is required.'));
278
+ console.log(kleur.red('\n Setup cancelled - Tenant ID is required.'));
217
279
  process.exit(1);
218
280
  }
219
281
 
220
282
  // Create .env file
221
283
  const envContent = `# TractStack Configuration
222
- PUBLIC_GO_BACKEND="${responses.goBackend}"
284
+ PUBLIC_GO_BACKEND="${finalResponses.goBackend}"
223
285
  PUBLIC_TENANTID="${finalTenantId}"
224
- PRIVATE_GO_BACKEND_PATH="${responses.goBackendPath.endsWith('/') ? responses.goBackendPath : responses.goBackendPath + '/'}"
225
- ${responses.enableMultiTenant ? 'PUBLIC_ENABLE_MULTI_TENANT="true"' : ''}
286
+ PRIVATE_GO_BACKEND_PATH="${finalResponses.goBackendPath.endsWith('/') ? finalResponses.goBackendPath : finalResponses.goBackendPath + '/'}"
287
+ ENABLE_MULTI_TENANT="${finalResponses.enableMultiTenant ? 'true' : 'false'}"
226
288
  `;
227
289
 
228
290
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro-tractstack",
3
- "version": "2.0.0-rc.5",
3
+ "version": "2.0.0-rc.7",
4
4
  "description": "Astro integration for TractStack - redeeming the web from boring experiences",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -176,7 +176,7 @@ const createdDate = created ? new Date(created) : new Date();
176
176
  >
177
177
  Tract Stack</a
178
178
  >
179
- &ndash; no-code community engine from{` `}
179
+ &ndash; the &#8220;free web press&#8221; by{` `}
180
180
  <a
181
181
  href="https://atriskmedia.com/?utm_source=tractstack&utm_medium=www&utm_campaign=community"
182
182
  class="font-bold underline hover:text-black"
@@ -110,13 +110,9 @@ const PanelSwitch = ({
110
110
  break;
111
111
 
112
112
  case 'style-parent-add':
113
- if (markdownNode && signal.className)
113
+ if (markdownNode)
114
114
  return (
115
- <StyleParentAddPanel
116
- node={markdownNode}
117
- layer={signal.layer || 0}
118
- className={signal.className}
119
- />
115
+ <StyleParentAddPanel node={markdownNode} layer={signal.layer || 0} />
120
116
  );
121
117
  break;
122
118
 
@@ -200,12 +196,11 @@ const PanelSwitch = ({
200
196
  break;
201
197
 
202
198
  case 'style-element-add':
203
- if (clickedNode && markdownNode && signal.className)
199
+ if (clickedNode && markdownNode)
204
200
  return (
205
201
  <StyleElementAddPanel
206
202
  node={clickedNode}
207
203
  parentNode={markdownNode}
208
- className={signal.className}
209
204
  onTitleChange={onTitleChange}
210
205
  />
211
206
  );
@@ -493,7 +493,7 @@ const AddPaneNewPanel = ({
493
493
  <Switch.HiddenInput />
494
494
  <div className="flex h-6 items-center">
495
495
  <Switch.Label className="px-4 text-sm text-gray-700">
496
- Use odd variant
496
+ Toggle subtle variation (great for stacking content)
497
497
  </Switch.Label>
498
498
  </div>
499
499
  </Switch.Root>
@@ -291,11 +291,13 @@ export default function RegistrationForm({
291
291
  value={state.email}
292
292
  onChange={(value) => updateField('email', value)}
293
293
  type="email"
294
- placeholder="john@example.com"
294
+ placeholder="susie@amazing.com"
295
295
  error={errors.email}
296
296
  />
297
297
  <p className="mt-1 text-sm text-gray-500">
298
- You'll receive an activation email at this address
298
+ {isInitMode
299
+ ? `Used for password reset, etc.`
300
+ : `You'll receive an activation email at this address`}
299
301
  </p>
300
302
  </div>
301
303
 
@@ -168,7 +168,13 @@ for (const [key, value] of Astro.url.searchParams) {
168
168
  <StoryKeepToolMode isContext={false} client:only="react" />
169
169
 
170
170
  <!-- Main Content Area -->
171
- <main id="mainContent" class="relative flex-1">
171
+ <main
172
+ id="mainContent"
173
+ class="relative flex-1"
174
+ style={{
175
+ paddingBottom: 'var(--bottom-right-controls-bottom-offset, 16px)',
176
+ }}
177
+ >
172
178
  <div class="bg-myblue/20 bg-mylightgrey h-full p-1.5">
173
179
  <div
174
180
  class="h-fit min-h-screen"
@@ -116,7 +116,7 @@ if (!brandConfig.SITE_INIT) {
116
116
  impressions={storyData.impressions || []}
117
117
  storyfragmentId={storyfragmentId}
118
118
  >
119
- <main id="main-content" class="min-h-screen w-full">
119
+ <main id="main-content" class="w-full">
120
120
  <div class="panes-container">
121
121
  {
122
122
  paneIds.map((paneId: string) => (
@@ -159,7 +159,13 @@ for (const [key, value] of Astro.url.searchParams) {
159
159
  <StoryKeepToolMode isContext={true} client:only="react" />
160
160
 
161
161
  <!-- Main Content Area -->
162
- <main id="mainContent" class="relative flex-1">
162
+ <main
163
+ id="mainContent"
164
+ class="relative flex-1"
165
+ style={{
166
+ paddingBottom: 'var(--bottom-right-controls-bottom-offset, 16px)',
167
+ }}
168
+ >
163
169
  <div class="bg-myblue/20 bg-mylightgrey h-full p-1.5">
164
170
  <div
165
171
  class="h-fit min-h-screen"
@@ -112,7 +112,7 @@ if (!brandConfig.SITE_INIT) {
112
112
  brandConfig={brandConfig}
113
113
  storyfragmentId={paneId}
114
114
  >
115
- <main id="main-content" class="min-h-screen w-full">
115
+ <main id="main-content" class="w-full">
116
116
  <div
117
117
  id={`pane-${paneId}`}
118
118
  data-pane-id={paneId}
@@ -359,6 +359,7 @@ export function getJustCopyDesign(
359
359
  baseClasses[2].mobile.textWRAP = 'pretty';
360
360
  baseClasses[2].mobile.maxW = '3xl';
361
361
  if (bordered) {
362
+ baseClasses[2].mobile.rounded = 'lg';
362
363
  baseClasses[2].mobile.bgCOLOR = getColor(
363
364
  {
364
365
  light: useOdd ? 'brand-2' : 'white',
@@ -383,6 +384,7 @@ export function getJustCopyDesign(
383
384
  baseClasses[2].mobile.textALIGN = 'center';
384
385
  baseClasses[2].mobile.textWRAP = 'balance';
385
386
  if (bordered) {
387
+ baseClasses[2].mobile.rounded = 'lg';
386
388
  baseClasses[2].mobile.bgCOLOR = getColor(
387
389
  {
388
390
  light: useOdd ? 'brand-2' : 'white',
@@ -405,6 +407,7 @@ export function getJustCopyDesign(
405
407
  baseClasses[2].mobile.textALIGN = 'left';
406
408
  baseClasses[2].mobile.textWRAP = 'pretty';
407
409
  if (bordered) {
410
+ baseClasses[2].mobile.rounded = 'lg';
408
411
  baseClasses[2].mobile.bgCOLOR = getColor(
409
412
  {
410
413
  light: useOdd ? 'brand-2' : 'white',
@@ -503,6 +506,7 @@ export function getSubTitleDesign(
503
506
  baseClasses[2].mobile.textWRAP = 'pretty';
504
507
  baseClasses[2].mobile.maxW = '3xl';
505
508
  if (bordered) {
509
+ baseClasses[2].mobile.rounded = 'lg';
506
510
  baseClasses[2].mobile.bgCOLOR = getColor(
507
511
  {
508
512
  light: useOdd ? 'brand-2' : 'white',
@@ -552,6 +556,7 @@ export function getSubTitleDesign(
552
556
  baseClasses[2].mobile.textALIGN = 'center';
553
557
  baseClasses[2].mobile.textWRAP = 'balance';
554
558
  if (bordered) {
559
+ baseClasses[2].mobile.rounded = 'lg';
555
560
  baseClasses[2].mobile.bgCOLOR = getColor(
556
561
  {
557
562
  light: useOdd ? 'brand-2' : 'white',
@@ -647,6 +652,7 @@ export function getSubTitleDesign(
647
652
  baseClasses[2].mobile.textALIGN = 'center';
648
653
  baseClasses[2].mobile.textWRAP = 'balance';
649
654
  if (bordered) {
655
+ baseClasses[2].mobile.rounded = 'lg';
650
656
  baseClasses[2].mobile.bgCOLOR = getColor(
651
657
  {
652
658
  light: useOdd ? 'brand-2' : 'white',
@@ -741,6 +747,7 @@ export function getSubTitleDesign(
741
747
  baseClasses[2].mobile.textALIGN = 'left';
742
748
  baseClasses[2].mobile.textWRAP = 'pretty';
743
749
  if (bordered) {
750
+ baseClasses[2].mobile.rounded = 'lg';
744
751
  baseClasses[2].mobile.bgCOLOR = getColor(
745
752
  {
746
753
  light: useOdd ? 'brand-2' : 'white',
@@ -986,6 +993,7 @@ export const getIntroDesign = (
986
993
  (parentClasses[2].mobile.textALIGN = 'center');
987
994
  parentClasses[2].mobile.textWRAP = 'balance';
988
995
  if (bordered) {
996
+ parentClasses[2].mobile.rounded = 'lg';
989
997
  parentClasses[2].mobile.bgCOLOR = getColor(
990
998
  {
991
999
  light: useOdd ? 'brand-2' : 'white',
@@ -31,6 +31,7 @@ export function startLoadingAnimation() {
31
31
  if (progressInterval !== null) {
32
32
  clearInterval(progressInterval);
33
33
  }
34
+ return;
34
35
  }
35
36
  loadingIndicator.style.transform = `scaleX(${progress / 100})`;
36
37
  }, 20);