astro-tractstack 2.0.0-rc.65 → 2.0.0-rc.66

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro-tractstack",
3
- "version": "2.0.0-rc.65",
3
+ "version": "2.0.0-rc.66",
4
4
  "description": "Astro integration for TractStack - redeeming the web from boring experiences",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -27,7 +27,7 @@ const SettingsPanel = ({ config, availableCodeHooks }: SettingsPanelProps) => {
27
27
 
28
28
  return (
29
29
  <div
30
- className="bg-mydarkgrey flex h-full max-w-sm flex-col rounded-xl bg-opacity-20 p-0.5 backdrop-blur-sm"
30
+ className="bg-mydarkgrey min-w-xs flex h-full max-w-sm flex-col rounded-xl bg-opacity-20 p-0.5 backdrop-blur-sm"
31
31
  style={
32
32
  {
33
33
  animation: window.matchMedia(
@@ -38,10 +38,7 @@ interface WidgetStyles {
38
38
  bgColor: string;
39
39
  bgOpacity: number;
40
40
  }
41
- type StoredDisclosureItem = Omit<
42
- DisclosureItem,
43
- 'id' | 'isDisabled' | 'isCustom'
44
- >;
41
+ type StoredDisclosureItem = Omit<DisclosureItem, 'id' | 'isDisabled'>;
45
42
  interface InteractiveDisclosureWidgetProps {
46
43
  node: FlatNode;
47
44
  onUpdate: (params: string[]) => void;
@@ -91,6 +88,7 @@ const IconSelector = ({
91
88
  <Combobox.Input
92
89
  className="w-full rounded-md border-gray-300 py-1.5 pl-3 pr-10 shadow-sm"
93
90
  placeholder="Search icons..."
91
+ autoFocus
94
92
  />
95
93
  <Combobox.Trigger className="absolute inset-y-0 right-0 flex items-center pr-2">
96
94
  <i className={`bi bi-${value} mr-2 text-lg`}></i>
@@ -141,6 +139,13 @@ const DisclosureItemEditor = ({
141
139
  isFirst: boolean;
142
140
  isLast: boolean;
143
141
  }) => {
142
+ const [isEditingIcon, setIsEditingIcon] = useState(false);
143
+
144
+ const handleIconChange = (newIcon: string) => {
145
+ onUpdate({ icon: newIcon });
146
+ setIsEditingIcon(false);
147
+ };
148
+
144
149
  return (
145
150
  <div
146
151
  className={`space-y-4 rounded-lg border bg-white p-4 shadow-sm transition-opacity ${
@@ -169,9 +174,11 @@ const DisclosureItemEditor = ({
169
174
  </div>
170
175
  <h4 className="font-bold text-gray-800">
171
176
  {item.title}{' '}
172
- <span className="text-xs font-normal text-gray-500">
173
- (Key: {item.beliefValue})
174
- </span>
177
+ {!item.isCustom && (
178
+ <span className="text-xs font-normal text-gray-500">
179
+ (Key: {item.beliefValue})
180
+ </span>
181
+ )}
175
182
  </h4>
176
183
  </div>
177
184
  <button
@@ -189,13 +196,6 @@ const DisclosureItemEditor = ({
189
196
  </button>
190
197
  </div>
191
198
  <fieldset disabled={item.isDisabled} className="space-y-4">
192
- {item.isCustom && (
193
- <SingleParam
194
- label="Key / Value"
195
- value={item.beliefValue}
196
- onChange={(value) => onUpdate({ beliefValue: value })}
197
- />
198
- )}
199
199
  <SingleParam
200
200
  label="Display Title"
201
201
  value={item.title}
@@ -206,10 +206,29 @@ const DisclosureItemEditor = ({
206
206
  value={item.description || ''}
207
207
  onChange={(value) => onUpdate({ description: value })}
208
208
  />
209
- <IconSelector
210
- value={item.icon}
211
- onChange={(value) => onUpdate({ icon: value })}
212
- />
209
+
210
+ {isEditingIcon ? (
211
+ <IconSelector value={item.icon} onChange={handleIconChange} />
212
+ ) : (
213
+ <div>
214
+ <label className="block text-xs font-bold text-gray-600">
215
+ Icon
216
+ </label>
217
+ <div className="mt-1 flex items-center justify-between rounded-md border border-gray-300 bg-white px-3 py-1.5 shadow-sm">
218
+ <div className="flex items-center gap-2">
219
+ <i className={`bi bi-${item.icon} text-lg`}></i>
220
+ <span className="text-sm">{item.icon}</span>
221
+ </div>
222
+ <button
223
+ type="button"
224
+ onClick={() => setIsEditingIcon(true)}
225
+ className="text-sm font-bold text-cyan-600 hover:text-cyan-800"
226
+ >
227
+ Change
228
+ </button>
229
+ </div>
230
+ </div>
231
+ )}
213
232
 
214
233
  {item.isCustom ? (
215
234
  <div className="relative rounded-md border p-3">
@@ -243,8 +262,8 @@ export default function InteractiveDisclosureWidget({
243
262
  const [selectedBeliefTag, setSelectedBeliefTag] = useState<string>('');
244
263
  const [disclosures, setDisclosures] = useState<DisclosureItem[]>([]);
245
264
  const [widgetStyles, setWidgetStyles] = useState<WidgetStyles>({
246
- textColor: '',
247
- bgColor: '',
265
+ textColor: '#000000',
266
+ bgColor: '#ffffff',
248
267
  bgOpacity: 100,
249
268
  });
250
269
  const [isModalOpen, setIsModalOpen] = useState(false);
@@ -268,7 +287,11 @@ export default function InteractiveDisclosureWidget({
268
287
  try {
269
288
  const parsed = JSON.parse(payloadJson);
270
289
  setWidgetStyles(
271
- parsed.styles || { textColor: '', bgColor: '', bgOpacity: 100 }
290
+ parsed.styles || {
291
+ textColor: '#000000',
292
+ bgColor: '#ffffff',
293
+ bgOpacity: 100,
294
+ }
272
295
  );
273
296
  const loadedDisclosures =
274
297
  (parsed.disclosures as StoredDisclosureItem[]) || [];
@@ -290,6 +313,7 @@ export default function InteractiveDisclosureWidget({
290
313
  const isFromScale = scaleKeys.some(
291
314
  (sk) => sk.slug === loadedItem.beliefValue
292
315
  );
316
+
293
317
  return {
294
318
  ...loadedItem,
295
319
  id: generateId(),
@@ -308,7 +332,7 @@ export default function InteractiveDisclosureWidget({
308
332
  beliefValue: slug,
309
333
  title: name,
310
334
  description: '',
311
- icon: 'app',
335
+ icon: 'chat-heart-fill',
312
336
  actionLisp: `(${actionCommand} ${beliefTag} ${quoteIfNecessary(actionCommand, slug)})`,
313
337
  isCustom: false,
314
338
  isDisabled: true,
@@ -321,7 +345,11 @@ export default function InteractiveDisclosureWidget({
321
345
  }
322
346
  } else {
323
347
  setDisclosures([]);
324
- setWidgetStyles({ textColor: '', bgColor: '', bgOpacity: 100 });
348
+ setWidgetStyles({
349
+ textColor: '#000000',
350
+ bgColor: '#ffffff',
351
+ bgOpacity: 100,
352
+ });
325
353
  }
326
354
  setIsDataLoaded(true);
327
355
  }, [node, beliefs]);
@@ -352,13 +380,18 @@ export default function InteractiveDisclosureWidget({
352
380
  const handleUpdate = () => {
353
381
  const disclosuresToStore: StoredDisclosureItem[] = disclosures
354
382
  .filter((d) => !d.isDisabled)
355
- .map(({ id, isCustom, isDisabled, ...rest }) => rest);
383
+ .map(({ id, isDisabled, ...rest }) => rest);
356
384
  const payload = { styles: widgetStyles, disclosures: disclosuresToStore };
357
385
  onUpdate([selectedBeliefTag, JSON.stringify(payload)]);
358
386
  };
359
387
 
360
388
  const handleBeliefChange = (tag: string) => {
361
389
  setSelectedBeliefTag(tag);
390
+ setWidgetStyles({
391
+ textColor: '#000000',
392
+ bgColor: '#ffffff',
393
+ bgOpacity: 100,
394
+ });
362
395
  const belief = beliefs.find((b) => b.slug === tag);
363
396
  let newDisclosures: DisclosureItem[] = [];
364
397
  if (belief) {
@@ -375,7 +408,7 @@ export default function InteractiveDisclosureWidget({
375
408
  beliefValue: slug,
376
409
  title: name,
377
410
  description: '',
378
- icon: 'app',
411
+ icon: 'chat-heart-fill',
379
412
  actionLisp: `(${actionCommand} ${tag} ${quoteIfNecessary(actionCommand, slug)})`,
380
413
  isCustom: false,
381
414
  isDisabled: false,
@@ -399,10 +432,12 @@ export default function InteractiveDisclosureWidget({
399
432
  const addCustomDisclosure = () => {
400
433
  const newItem: DisclosureItem = {
401
434
  id: generateId(),
402
- beliefValue: `custom-key-${disclosures.length + 1}`,
435
+ beliefValue: `custom-${Date.now()}-${Math.random()
436
+ .toString(36)
437
+ .substring(2, 6)}`,
403
438
  title: 'New Custom Item',
404
439
  description: '',
405
- icon: 'plus-circle',
440
+ icon: 'chat-heart-fill',
406
441
  actionLisp: '',
407
442
  isCustom: true,
408
443
  isDisabled: false,
@@ -418,12 +453,20 @@ export default function InteractiveDisclosureWidget({
418
453
  const updateWidgetStyles = (updates: Partial<WidgetStyles>) =>
419
454
  setWidgetStyles((prev) => ({ ...prev, ...updates }));
420
455
 
421
- const toggleDisclosure = (id: string) =>
422
- setDisclosures(
423
- disclosures.map((d) =>
424
- d.id === id ? { ...d, isDisabled: !d.isDisabled } : d
425
- )
426
- );
456
+ const toggleDisclosure = (id: string) => {
457
+ const itemToToggle = disclosures.find((d) => d.id === id);
458
+ if (!itemToToggle) return;
459
+
460
+ if (itemToToggle.isCustom) {
461
+ setDisclosures(disclosures.filter((d) => d.id !== id));
462
+ } else {
463
+ setDisclosures(
464
+ disclosures.map((d) =>
465
+ d.id === id ? { ...d, isDisabled: !d.isDisabled } : d
466
+ )
467
+ );
468
+ }
469
+ };
427
470
 
428
471
  const handleColorChange = (
429
472
  key: 'textColor' | 'bgColor',
@@ -171,7 +171,7 @@ for (const [key, value] of Astro.url.searchParams) {
171
171
  <main id="mainContent" class="relative flex-1 overflow-x-auto">
172
172
  <div class="bg-myblue/20 bg-mylightgrey h-full p-1.5">
173
173
  <div
174
- class="h-fit min-h-screen pb-24"
174
+ class="h-fit min-h-screen pb-96"
175
175
  style={{
176
176
  backgroundImage:
177
177
  'repeating-linear-gradient(135deg, transparent, transparent 10px, rgba(0,0,0,0.05) 10px, rgba(0,0,0,0.05) 20px)',
@@ -159,16 +159,10 @@ 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
163
- id="mainContent"
164
- class="relative flex-1 overflow-x-auto"
165
- style={{
166
- paddingBottom: 'var(--bottom-right-controls-bottom-offset, 16px)',
167
- }}
168
- >
162
+ <main id="mainContent" class="relative flex-1 overflow-x-auto">
169
163
  <div class="bg-myblue/20 bg-mylightgrey h-full p-1.5">
170
164
  <div
171
- class="h-fit min-h-screen"
165
+ class="h-fit min-h-screen pb-96"
172
166
  style={{
173
167
  backgroundImage:
174
168
  'repeating-linear-gradient(135deg, transparent, transparent 10px, rgba(0,0,0,0.05) 10px, rgba(0,0,0,0.05) 20px)',