astro-tractstack 2.3.1 → 2.3.3
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/bin/create-tractstack.js +3 -3
- package/dist/index.js +69 -11
- package/package.json +1 -1
- package/templates/custom/shopify/Cart.tsx +99 -19
- package/templates/custom/shopify/CheckoutModal.tsx +196 -10
- package/templates/custom/shopify/ShopifyCartManager.tsx +79 -76
- package/templates/custom/shopify/ShopifyCheckout.tsx +4 -33
- package/templates/custom/shopify/ShopifyProductGrid.tsx +42 -14
- package/templates/custom/shopify/ShopifyServiceList.tsx +94 -50
- package/templates/custom/shopify/cart.astro +7 -1
- package/templates/src/components/Footer.astro +2 -2
- package/templates/src/components/Header.astro +17 -9
- package/templates/src/components/Menu.tsx +157 -135
- package/templates/src/components/codehooks/BunnyVideoSetup.tsx +2 -2
- package/templates/src/components/codehooks/EpinetDurationSelector.tsx +27 -6
- package/templates/src/components/codehooks/EpinetTableView.tsx +153 -112
- package/templates/src/components/codehooks/EpinetWrapper.tsx +4 -1
- package/templates/src/components/codehooks/FeaturedArticleSetup.tsx +8 -1
- package/templates/src/components/codehooks/ProductCardSetup.tsx +9 -1
- package/templates/src/components/codehooks/ProductGridSetup.tsx +9 -1
- package/templates/src/components/compositor/nodes/BgPaneWrapper.tsx +2 -1
- package/templates/src/components/compositor/nodes/GhostInsertBlock.tsx +1 -1
- package/templates/src/components/edit/ToolBar.tsx +2 -1
- package/templates/src/components/edit/context/ContextPaneConfig_slug.tsx +2 -2
- package/templates/src/components/edit/pane/AddPanePanel_codehook.tsx +13 -0
- package/templates/src/components/edit/pane/AddPanePanel_newCustomCopy.tsx +2 -2
- package/templates/src/components/edit/pane/ConfigPanePanel.tsx +1 -1
- package/templates/src/components/edit/state/SaveModal.tsx +1 -1
- package/templates/src/components/edit/widgets/InteractiveDisclosureWidget.tsx +8 -3
- package/templates/src/components/form/DateTimeInput.tsx +10 -3
- package/templates/src/components/form/FileUpload.tsx +11 -5
- package/templates/src/components/form/NumberInput.tsx +2 -2
- package/templates/src/components/form/advanced/APIConfigSection.tsx +221 -39
- package/templates/src/components/form/brand/SiteConfigSection.tsx +10 -0
- package/templates/src/components/form/shopify/SchedulingSection.tsx +44 -0
- package/templates/src/components/storykeep/Dashboard_Advanced.tsx +10 -1
- package/templates/src/components/storykeep/Dashboard_Shopify.tsx +16 -8
- package/templates/src/components/storykeep/controls/content/BeliefForm.tsx +2 -2
- package/templates/src/components/storykeep/controls/content/ManageContent.tsx +1 -0
- package/templates/src/components/storykeep/controls/content/ProductTable.tsx +2 -2
- package/templates/src/components/storykeep/controls/content/ResourceBulkIngest.tsx +79 -51
- package/templates/src/components/storykeep/controls/content/ResourceForm.tsx +80 -0
- package/templates/src/components/storykeep/controls/content/ResourceTable.tsx +1 -0
- package/templates/src/components/storykeep/email-builder/Blocks.tsx +169 -0
- package/templates/src/components/storykeep/email-builder/EmailBuilder.tsx +223 -0
- package/templates/src/components/storykeep/email-builder/PreviewModal.tsx +136 -0
- package/templates/src/components/storykeep/email-builder/PropertyPanel.tsx +154 -0
- package/templates/src/components/storykeep/shopify/ShopifyDashboard.tsx +1 -8
- package/templates/src/components/storykeep/shopify/ShopifyDashboard_Bookings.tsx +118 -14
- package/templates/src/components/storykeep/shopify/ShopifyDashboard_Emails.tsx +105 -0
- package/templates/src/constants.ts +2 -0
- package/templates/src/layouts/Layout.astro +8 -5
- package/templates/src/pages/api/google/oauth/callback.ts +50 -0
- package/templates/src/pages/api/google/oauth/disconnect.ts +32 -0
- package/templates/src/pages/api/google/oauth/start.ts +32 -0
- package/templates/src/pages/api/google/oauth/status.ts +32 -0
- package/templates/src/pages/privacy.astro +84 -0
- package/templates/src/pages/terms.astro +47 -0
- package/templates/src/stores/shopify.ts +21 -0
- package/templates/src/types/formTypes.ts +4 -2
- package/templates/src/types/tractstack.ts +35 -2
- package/templates/src/utils/api/advancedHelpers.ts +16 -0
- package/templates/src/utils/api/bookingHelpers.ts +3 -1
- package/templates/src/utils/api/brandConfig.ts +2 -0
- package/templates/src/utils/api/brandHelpers.ts +24 -1
- package/templates/src/utils/api/emailHelpers.ts +105 -0
- package/templates/src/utils/booking/appointmentMode.ts +135 -0
- package/templates/src/utils/customHelpers.ts +2 -0
- package/templates/src/utils/tenantResolver.ts +1 -1
- package/utils/inject-files.ts +63 -5
- package/templates/src/components/codehooks/SandboxAuthWrapper.tsx +0 -101
- package/templates/src/utils/actions/actionButton.ts +0 -103
- package/templates/src/utils/actions/preParse_Clicked.ts +0 -87
|
@@ -2,7 +2,10 @@ import { useState, useEffect } from 'react';
|
|
|
2
2
|
import { useStore } from '@nanostores/react';
|
|
3
3
|
import { createListCollection } from '@ark-ui/react/collection';
|
|
4
4
|
import { Select } from '@ark-ui/react/select';
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
RadioGroup,
|
|
7
|
+
useRadioGroupItemContext,
|
|
8
|
+
} from '@ark-ui/react/radio-group';
|
|
6
9
|
import { Portal } from '@ark-ui/react/portal';
|
|
7
10
|
import XMarkIcon from '@heroicons/react/24/outline/XMarkIcon';
|
|
8
11
|
import CheckCircleIcon from '@heroicons/react/24/outline/CheckCircleIcon';
|
|
@@ -49,6 +52,15 @@ interface AvailableFilter {
|
|
|
49
52
|
values: string[];
|
|
50
53
|
}
|
|
51
54
|
|
|
55
|
+
const VisitorTypeCheckIcon = () => {
|
|
56
|
+
const { checked } = useRadioGroupItemContext();
|
|
57
|
+
return (
|
|
58
|
+
<div className={`shrink-0 text-cyan-600 ${checked ? 'block' : 'hidden'}`}>
|
|
59
|
+
<CheckCircleIcon className="h-5 w-5" />
|
|
60
|
+
</div>
|
|
61
|
+
);
|
|
62
|
+
};
|
|
63
|
+
|
|
52
64
|
interface EpinetDurationSelectorProps {
|
|
53
65
|
fullContentMap?: ContentMapItem[];
|
|
54
66
|
isLoading?: boolean;
|
|
@@ -382,6 +394,16 @@ const EpinetDurationSelector = ({
|
|
|
382
394
|
@media (min-width: 641px) { .radio-item { flex: 1 1 calc(33.333% - 0.5rem); } }
|
|
383
395
|
`;
|
|
384
396
|
|
|
397
|
+
const epinetUserSelectItemStyles = `
|
|
398
|
+
.epinet-user-select-item[data-highlighted] {
|
|
399
|
+
background-color: #0891b2;
|
|
400
|
+
color: #fff;
|
|
401
|
+
}
|
|
402
|
+
.epinet-user-select-item[data-highlighted] .text-gray-500 {
|
|
403
|
+
color: rgb(229 231 235);
|
|
404
|
+
}
|
|
405
|
+
`;
|
|
406
|
+
|
|
385
407
|
const getFilterStatusMessage = () => {
|
|
386
408
|
const needsApply = hasLocalChanges;
|
|
387
409
|
const prefix = needsApply ? 'Press Apply Filters to load' : 'Showing';
|
|
@@ -546,6 +568,7 @@ const EpinetDurationSelector = ({
|
|
|
546
568
|
<div className="duration-selector-container flex flex-col space-y-4 md:space-y-0">
|
|
547
569
|
<div className="space-y-2">
|
|
548
570
|
<style>{radioGroupStyles}</style>
|
|
571
|
+
<style>{epinetUserSelectItemStyles}</style>
|
|
549
572
|
<RadioGroup.Root
|
|
550
573
|
value={localFilters.visitorType}
|
|
551
574
|
onValueChange={({ value }) =>
|
|
@@ -579,9 +602,7 @@ const EpinetDurationSelector = ({
|
|
|
579
602
|
</div>
|
|
580
603
|
</RadioGroup.ItemText>
|
|
581
604
|
</div>
|
|
582
|
-
<
|
|
583
|
-
<CheckCircleIcon className="h-5 w-5" />
|
|
584
|
-
</div>
|
|
605
|
+
<VisitorTypeCheckIcon />
|
|
585
606
|
</div>
|
|
586
607
|
<RadioGroup.ItemHiddenInput />
|
|
587
608
|
</RadioGroup.Item>
|
|
@@ -817,7 +838,7 @@ const EpinetDurationSelector = ({
|
|
|
817
838
|
<Select.Item
|
|
818
839
|
key="empty"
|
|
819
840
|
item={{ value: '', label: 'Select user' }}
|
|
820
|
-
className="cursor-pointer select-none p-2 text-sm text-gray-500 hover:bg-slate-100
|
|
841
|
+
className="epinet-user-select-item cursor-pointer select-none p-2 text-sm text-gray-500 hover:bg-slate-100"
|
|
821
842
|
>
|
|
822
843
|
<Select.ItemText>
|
|
823
844
|
Select user
|
|
@@ -830,7 +851,7 @@ const EpinetDurationSelector = ({
|
|
|
830
851
|
value: user.id,
|
|
831
852
|
label: `${user.id} (${user.count} events)`,
|
|
832
853
|
}}
|
|
833
|
-
className="cursor-pointer select-none p-2 text-sm text-gray-700 hover:bg-slate-100
|
|
854
|
+
className="epinet-user-select-item cursor-pointer select-none p-2 text-sm text-gray-700 hover:bg-slate-100"
|
|
834
855
|
>
|
|
835
856
|
<Select.ItemText>
|
|
836
857
|
{user.id}{' '}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useState, useEffect } from 'react';
|
|
2
2
|
import { useStore } from '@nanostores/react';
|
|
3
|
+
import { classNames } from '@/utils/helpers';
|
|
3
4
|
import { epinetCustomFilters } from '@/stores/analytics';
|
|
4
5
|
import { Accordion } from '@ark-ui/react';
|
|
5
6
|
import ChevronLeftIcon from '@heroicons/react/24/outline/ChevronLeftIcon';
|
|
@@ -68,6 +69,7 @@ const EpinetTableView = ({
|
|
|
68
69
|
const [currentDay, setCurrentDay] = useState<string | null>(null);
|
|
69
70
|
const [availableDays, setAvailableDays] = useState<string[]>([]);
|
|
70
71
|
const [currentDayIndex, setCurrentDayIndex] = useState(0);
|
|
72
|
+
const [openAccordionValues, setOpenAccordionValues] = useState<string[]>([]);
|
|
71
73
|
|
|
72
74
|
const getContentInfo = (
|
|
73
75
|
contentId: string
|
|
@@ -215,6 +217,12 @@ const EpinetTableView = ({
|
|
|
215
217
|
setCurrentDay(availableDays[newIndex]);
|
|
216
218
|
};
|
|
217
219
|
|
|
220
|
+
useEffect(() => {
|
|
221
|
+
setOpenAccordionValues((prev) =>
|
|
222
|
+
prev.filter((v) => !v.startsWith('empty-'))
|
|
223
|
+
);
|
|
224
|
+
}, [currentDay]);
|
|
225
|
+
|
|
218
226
|
const getCurrentDayData = (): {
|
|
219
227
|
data: HourData[];
|
|
220
228
|
dailyTotal: number;
|
|
@@ -485,129 +493,162 @@ const EpinetTableView = ({
|
|
|
485
493
|
</div>
|
|
486
494
|
</div>
|
|
487
495
|
|
|
488
|
-
<Accordion.Root
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
496
|
+
<Accordion.Root
|
|
497
|
+
multiple
|
|
498
|
+
className="w-full"
|
|
499
|
+
value={openAccordionValues}
|
|
500
|
+
onValueChange={({ value }) =>
|
|
501
|
+
setOpenAccordionValues(value.filter((v) => !v.startsWith('empty-')))
|
|
502
|
+
}
|
|
503
|
+
>
|
|
504
|
+
{dayData.map((item, index) => {
|
|
505
|
+
const itemValue =
|
|
506
|
+
item.type === 'active' ? item.hourKey : `empty-${index}`;
|
|
507
|
+
const isExpandable = item.type === 'active';
|
|
508
|
+
const isOpen = openAccordionValues.includes(itemValue);
|
|
509
|
+
return (
|
|
510
|
+
<Accordion.Item
|
|
511
|
+
key={item.type === 'active' ? item.hourKey : `empty-${index}`}
|
|
512
|
+
value={itemValue}
|
|
513
|
+
disabled={!isExpandable}
|
|
514
|
+
className="border-b border-gray-100 last:border-b-0"
|
|
515
|
+
>
|
|
516
|
+
<Accordion.ItemTrigger
|
|
517
|
+
className={classNames(
|
|
518
|
+
'flex w-full items-center justify-between p-3 text-left transition-colors duration-200',
|
|
519
|
+
isExpandable
|
|
520
|
+
? 'cursor-pointer hover:bg-gray-100'
|
|
521
|
+
: 'cursor-default hover:bg-transparent'
|
|
522
|
+
)}
|
|
523
|
+
>
|
|
524
|
+
{item.type === 'active' ? (
|
|
525
|
+
<div className="flex flex-grow items-center justify-between space-x-3">
|
|
526
|
+
<div className="flex flex-grow items-center space-x-3">
|
|
527
|
+
<span className="text-sm font-bold text-gray-700">
|
|
528
|
+
{item.humanReadableTime}
|
|
529
|
+
</span>
|
|
530
|
+
<span className="text-xs text-gray-600">
|
|
531
|
+
{item.hourlyTotal} event
|
|
532
|
+
{item.hourlyTotal !== 1 ? 's' : ''} /{' '}
|
|
533
|
+
{item.hourlyVisitors} visitor
|
|
534
|
+
{item.hourlyVisitors !== 1 ? 's' : ''}
|
|
535
|
+
</span>
|
|
536
|
+
<div className="relative h-2 w-full max-w-48 rounded bg-gray-200">
|
|
537
|
+
<div
|
|
538
|
+
className="absolute left-0 top-0 h-2 rounded bg-cyan-600"
|
|
539
|
+
style={{
|
|
540
|
+
width: `${Math.max(item.relativeToMax * 100, 5)}%`,
|
|
541
|
+
}}
|
|
542
|
+
title={`${item.hourlyTotal} events (${(
|
|
543
|
+
item.relativeToMax * 100
|
|
544
|
+
).toFixed(1)}% of busiest hour)`}
|
|
545
|
+
/>
|
|
546
|
+
</div>
|
|
518
547
|
</div>
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
onClick={(e) => {
|
|
523
|
-
e.stopPropagation();
|
|
524
|
-
focusOnThisHour(item.hourKey);
|
|
525
|
-
}}
|
|
526
|
-
className="flex cursor-pointer items-center rounded-md bg-orange-100 px-2 py-1 text-xs font-bold text-orange-800 transition-colors duration-200 hover:bg-orange-200"
|
|
527
|
-
role="button"
|
|
528
|
-
tabIndex={0}
|
|
529
|
-
onKeyDown={(e) => {
|
|
530
|
-
if (e.key === 'Enter' || e.key === ' ') {
|
|
531
|
-
e.preventDefault();
|
|
548
|
+
<div className="flex items-center space-x-2">
|
|
549
|
+
<div
|
|
550
|
+
onClick={(e) => {
|
|
532
551
|
e.stopPropagation();
|
|
533
552
|
focusOnThisHour(item.hourKey);
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
553
|
+
}}
|
|
554
|
+
className="flex cursor-pointer items-center rounded-md bg-orange-100 px-2 py-1 text-xs font-bold text-orange-800 transition-colors duration-200 hover:bg-orange-200"
|
|
555
|
+
role="button"
|
|
556
|
+
tabIndex={0}
|
|
557
|
+
onKeyDown={(e) => {
|
|
558
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
559
|
+
e.preventDefault();
|
|
560
|
+
e.stopPropagation();
|
|
561
|
+
focusOnThisHour(item.hourKey);
|
|
562
|
+
}
|
|
563
|
+
}}
|
|
564
|
+
>
|
|
565
|
+
<MagnifyingGlassIcon className="mr-1 h-3 w-3" />
|
|
566
|
+
Journeys this Hour
|
|
567
|
+
</div>
|
|
568
|
+
<div className="flex items-center rounded-md bg-orange-100 px-2 py-1 text-xs font-bold text-orange-800">
|
|
569
|
+
<Accordion.ItemIndicator>
|
|
570
|
+
<ChevronDownIcon
|
|
571
|
+
className={classNames(
|
|
572
|
+
'h-3 w-3 transition-transform duration-200',
|
|
573
|
+
isOpen && 'rotate-180'
|
|
574
|
+
)}
|
|
575
|
+
/>
|
|
576
|
+
</Accordion.ItemIndicator>
|
|
577
|
+
<span
|
|
578
|
+
className={classNames(
|
|
579
|
+
'ml-1',
|
|
580
|
+
isOpen ? 'hidden' : 'block'
|
|
581
|
+
)}
|
|
582
|
+
>
|
|
583
|
+
Expand Details
|
|
584
|
+
</span>
|
|
585
|
+
<span
|
|
586
|
+
className={classNames(
|
|
587
|
+
'ml-1',
|
|
588
|
+
isOpen ? 'block' : 'hidden'
|
|
589
|
+
)}
|
|
590
|
+
>
|
|
591
|
+
Hide Details
|
|
592
|
+
</span>
|
|
593
|
+
</div>
|
|
539
594
|
</div>
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
<span className="
|
|
545
|
-
|
|
595
|
+
</div>
|
|
596
|
+
) : (
|
|
597
|
+
<div className="flex flex-grow items-center">
|
|
598
|
+
<div className="flex items-center">
|
|
599
|
+
<span className="text-sm text-gray-700">
|
|
600
|
+
{item.humanReadableDisplay}
|
|
546
601
|
</span>
|
|
547
|
-
<span className="ml-
|
|
548
|
-
|
|
602
|
+
<span className="ml-2 text-xs italic text-gray-500">
|
|
603
|
+
{item.isFuture ? 'The future awaits!' : 'No activity'}
|
|
549
604
|
</span>
|
|
550
605
|
</div>
|
|
551
606
|
</div>
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
)}
|
|
568
|
-
</Accordion.ItemTrigger>
|
|
569
|
-
|
|
570
|
-
<Accordion.ItemContent className="p-4">
|
|
571
|
-
{item.type === 'active' && (
|
|
572
|
-
<div className="space-y-4">
|
|
573
|
-
{item.contentItems.map((content) => (
|
|
574
|
-
<div
|
|
575
|
-
key={`${item.hourKey}-${content.contentId}`}
|
|
576
|
-
className="mb-3"
|
|
577
|
-
>
|
|
578
|
-
<div className="mb-1 flex items-center justify-between text-sm font-bold text-gray-700">
|
|
579
|
-
<div className="flex items-center">
|
|
580
|
-
{getContentIcon(content.contentType)}
|
|
581
|
-
{content.title}
|
|
582
|
-
</div>
|
|
583
|
-
{content.visitorIds.length > 0 && (
|
|
584
|
-
<div
|
|
585
|
-
className="flex items-center text-xs text-gray-600"
|
|
586
|
-
title={content.visitorIds.join(', ')}
|
|
587
|
-
>
|
|
588
|
-
<UserGroupIcon className="mr-1 h-3 w-3" />
|
|
589
|
-
{content.visitorIds.length} unique visitor
|
|
590
|
-
{content.visitorIds.length !== 1 ? 's' : ''}
|
|
591
|
-
</div>
|
|
592
|
-
)}
|
|
593
|
-
</div>
|
|
594
|
-
<div className="flex flex-wrap gap-2">
|
|
595
|
-
{content.events.map((event, eventIdx) => (
|
|
596
|
-
<div
|
|
597
|
-
key={`${item.hourKey}-${content.contentId}-${event.verb}-${eventIdx}`}
|
|
598
|
-
className="rounded-full bg-cyan-100 px-2 py-0.5 text-xs font-bold text-cyan-800"
|
|
599
|
-
>
|
|
600
|
-
{event.verb} [{event.count}]
|
|
607
|
+
)}
|
|
608
|
+
</Accordion.ItemTrigger>
|
|
609
|
+
|
|
610
|
+
{isExpandable && (
|
|
611
|
+
<Accordion.ItemContent className="p-4">
|
|
612
|
+
<div className="space-y-4">
|
|
613
|
+
{item.contentItems.map((content) => (
|
|
614
|
+
<div
|
|
615
|
+
key={`${item.hourKey}-${content.contentId}`}
|
|
616
|
+
className="mb-3"
|
|
617
|
+
>
|
|
618
|
+
<div className="mb-1 flex items-center justify-between text-sm font-bold text-gray-700">
|
|
619
|
+
<div className="flex items-center">
|
|
620
|
+
{getContentIcon(content.contentType)}
|
|
621
|
+
{content.title}
|
|
601
622
|
</div>
|
|
602
|
-
|
|
623
|
+
{content.visitorIds.length > 0 && (
|
|
624
|
+
<div
|
|
625
|
+
className="flex items-center text-xs text-gray-600"
|
|
626
|
+
title={content.visitorIds.join(', ')}
|
|
627
|
+
>
|
|
628
|
+
<UserGroupIcon className="mr-1 h-3 w-3" />
|
|
629
|
+
{content.visitorIds.length} unique visitor
|
|
630
|
+
{content.visitorIds.length !== 1 ? 's' : ''}
|
|
631
|
+
</div>
|
|
632
|
+
)}
|
|
633
|
+
</div>
|
|
634
|
+
<div className="flex flex-wrap gap-2">
|
|
635
|
+
{content.events.map((event, eventIdx) => (
|
|
636
|
+
<div
|
|
637
|
+
key={`${item.hourKey}-${content.contentId}-${event.verb}-${eventIdx}`}
|
|
638
|
+
className="rounded-full bg-cyan-100 px-2 py-0.5 text-xs font-bold text-cyan-800"
|
|
639
|
+
>
|
|
640
|
+
{event.verb} [{event.count}]
|
|
641
|
+
</div>
|
|
642
|
+
))}
|
|
643
|
+
</div>
|
|
603
644
|
</div>
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
</
|
|
645
|
+
))}
|
|
646
|
+
</div>
|
|
647
|
+
</Accordion.ItemContent>
|
|
607
648
|
)}
|
|
608
|
-
</Accordion.
|
|
609
|
-
|
|
610
|
-
)
|
|
649
|
+
</Accordion.Item>
|
|
650
|
+
);
|
|
651
|
+
})}
|
|
611
652
|
|
|
612
653
|
{dayData.length === 0 && (
|
|
613
654
|
<div className="py-6 text-center text-sm text-gray-500">
|
|
@@ -269,7 +269,10 @@ const EpinetWrapper = ({
|
|
|
269
269
|
return (
|
|
270
270
|
<div className="flex h-96 w-full items-center justify-center rounded bg-gray-100">
|
|
271
271
|
<div className="text-center">
|
|
272
|
-
<div
|
|
272
|
+
<div
|
|
273
|
+
className="inline-block h-8 w-8 animate-spin rounded-full border-4 border-solid border-cyan-600 border-r-transparent motion-reduce:animate-none"
|
|
274
|
+
style={{ verticalAlign: '-0.125em' }}
|
|
275
|
+
></div>
|
|
273
276
|
<p className="mt-4 text-sm text-gray-600">
|
|
274
277
|
Discovering analytics configuration...
|
|
275
278
|
</p>
|
|
@@ -22,6 +22,13 @@ const comboboxItemStyles = `
|
|
|
22
22
|
.combo-item[data-state="checked"] .check-indicator {
|
|
23
23
|
display: flex;
|
|
24
24
|
}
|
|
25
|
+
.combo-item[data-highlighted] {
|
|
26
|
+
background-color: #0891b2;
|
|
27
|
+
color: #fff;
|
|
28
|
+
}
|
|
29
|
+
.combo-item[data-highlighted] .check-indicator {
|
|
30
|
+
color: #fff;
|
|
31
|
+
}
|
|
25
32
|
`;
|
|
26
33
|
|
|
27
34
|
const FeaturedArticleSetup = ({
|
|
@@ -268,7 +275,7 @@ const FeaturedArticleSetup = ({
|
|
|
268
275
|
<Combobox.Item
|
|
269
276
|
key={item.slug}
|
|
270
277
|
item={item}
|
|
271
|
-
className="combo-item relative cursor-default select-none py-2 pl-10 pr-4 text-gray-900
|
|
278
|
+
className="combo-item relative cursor-default select-none py-2 pl-10 pr-4 text-gray-900"
|
|
272
279
|
>
|
|
273
280
|
<span className="block truncate">{item.title}</span>
|
|
274
281
|
<span className="check-indicator absolute inset-y-0 left-0 flex items-center pl-3 text-cyan-600">
|
|
@@ -7,6 +7,13 @@ import { fullContentMapStore } from '@/stores/storykeep';
|
|
|
7
7
|
import { getCtx } from '@/stores/nodes';
|
|
8
8
|
import type { PaneNode } from '@/types/compositorTypes';
|
|
9
9
|
|
|
10
|
+
const productCardComboItemHighlightStyles = `
|
|
11
|
+
.product-card-combo-item[data-highlighted] {
|
|
12
|
+
background-color: #0891b2;
|
|
13
|
+
color: #fff;
|
|
14
|
+
}
|
|
15
|
+
`;
|
|
16
|
+
|
|
10
17
|
interface ProductCardSetupProps {
|
|
11
18
|
nodeId: string;
|
|
12
19
|
params: Record<string, any> | null;
|
|
@@ -118,6 +125,7 @@ export const ProductCardSetup = (props: ProductCardSetupProps) => {
|
|
|
118
125
|
<Combobox.Label className="text-sm font-bold text-gray-700">
|
|
119
126
|
Find a product
|
|
120
127
|
</Combobox.Label>
|
|
128
|
+
<style>{productCardComboItemHighlightStyles}</style>
|
|
121
129
|
<Combobox.Control>
|
|
122
130
|
<Combobox.Input
|
|
123
131
|
className="w-full rounded-md border-gray-300 px-3 py-2 shadow-sm focus:border-cyan-500 focus:ring-cyan-500 md:text-sm"
|
|
@@ -131,7 +139,7 @@ export const ProductCardSetup = (props: ProductCardSetupProps) => {
|
|
|
131
139
|
<Combobox.Item
|
|
132
140
|
key={item.value}
|
|
133
141
|
item={item}
|
|
134
|
-
className="relative cursor-pointer select-none px-4 py-2 text-gray-900
|
|
142
|
+
className="product-card-combo-item relative cursor-pointer select-none px-4 py-2 text-gray-900"
|
|
135
143
|
>
|
|
136
144
|
<Combobox.ItemText>{item.label}</Combobox.ItemText>
|
|
137
145
|
</Combobox.Item>
|
|
@@ -35,6 +35,13 @@ const modes = [
|
|
|
35
35
|
},
|
|
36
36
|
];
|
|
37
37
|
|
|
38
|
+
const productGridComboItemHighlightStyles = `
|
|
39
|
+
.product-grid-combo-item[data-highlighted] {
|
|
40
|
+
background-color: #0891b2;
|
|
41
|
+
color: #fff;
|
|
42
|
+
}
|
|
43
|
+
`;
|
|
44
|
+
|
|
38
45
|
export const ProductGridSetup = (props: ProductGridSetupProps) => {
|
|
39
46
|
const { nodeId, params } = props;
|
|
40
47
|
const ctx = getCtx();
|
|
@@ -235,6 +242,7 @@ export const ProductGridSetup = (props: ProductGridSetupProps) => {
|
|
|
235
242
|
<Combobox.Label className="text-sm font-bold text-gray-700">
|
|
236
243
|
Find products to include
|
|
237
244
|
</Combobox.Label>
|
|
245
|
+
<style>{productGridComboItemHighlightStyles}</style>
|
|
238
246
|
<Combobox.Control>
|
|
239
247
|
<Combobox.Input
|
|
240
248
|
className="w-full rounded-md border-gray-300 px-3 py-2 shadow-sm focus:border-cyan-500 focus:ring-cyan-500 md:text-sm"
|
|
@@ -248,7 +256,7 @@ export const ProductGridSetup = (props: ProductGridSetupProps) => {
|
|
|
248
256
|
<Combobox.Item
|
|
249
257
|
key={item.value}
|
|
250
258
|
item={item}
|
|
251
|
-
className="relative flex cursor-pointer select-none items-center px-4 py-2 text-gray-900
|
|
259
|
+
className="product-grid-combo-item relative flex cursor-pointer select-none items-center px-4 py-2 text-gray-900"
|
|
252
260
|
>
|
|
253
261
|
<Combobox.ItemText>{item.label}</Combobox.ItemText>
|
|
254
262
|
<Combobox.ItemIndicator className="ml-auto">
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { MouseEvent } from 'react';
|
|
1
2
|
import { getCtx } from '@/stores/nodes';
|
|
2
3
|
import { viewportKeyStore } from '@/stores/storykeep';
|
|
3
4
|
import {
|
|
@@ -15,7 +16,7 @@ export const BgPaneWrapper = (props: NodeProps) => {
|
|
|
15
16
|
|
|
16
17
|
const viewport = viewportKeyStore.get().value;
|
|
17
18
|
|
|
18
|
-
const handleClick = (e:
|
|
19
|
+
const handleClick = (e: MouseEvent) => {
|
|
19
20
|
getCtx(props).setClickedNodeId(props.nodeId, true);
|
|
20
21
|
e.stopPropagation();
|
|
21
22
|
};
|
|
@@ -85,7 +85,7 @@ export const GhostInsertBlock = memo((props: GhostInsertBlockProps) => {
|
|
|
85
85
|
setShowInsertOptions(false);
|
|
86
86
|
};
|
|
87
87
|
|
|
88
|
-
const handleClose = (e:
|
|
88
|
+
const handleClose = (e: MouseEvent) => {
|
|
89
89
|
e.stopPropagation();
|
|
90
90
|
getCtx(props).setPanelMode('', '', '');
|
|
91
91
|
setShowInsertOptions(false);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { MouseEvent } from 'react';
|
|
1
2
|
import { useStore } from '@nanostores/react';
|
|
2
3
|
import XMarkIcon from '@heroicons/react/24/outline/XMarkIcon';
|
|
3
4
|
import { getCtx } from '@/stores/nodes';
|
|
@@ -20,7 +21,7 @@ const AddElementsPanel = ({
|
|
|
20
21
|
ctx.notifyNode('root');
|
|
21
22
|
};
|
|
22
23
|
|
|
23
|
-
const handleMouseDown = (e:
|
|
24
|
+
const handleMouseDown = (e: MouseEvent, mode: ToolAddMode) => {
|
|
24
25
|
e.preventDefault();
|
|
25
26
|
startToolDrag('insert', mode, e.clientX, e.clientY);
|
|
26
27
|
initToolDragListeners();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState, useEffect } from 'react';
|
|
1
|
+
import { useState, useEffect, type ChangeEvent } from 'react';
|
|
2
2
|
import ExclamationTriangleIcon from '@heroicons/react/24/outline/ExclamationTriangleIcon';
|
|
3
3
|
import CheckIcon from '@heroicons/react/24/outline/CheckIcon';
|
|
4
4
|
import { getCtx } from '@/stores/nodes';
|
|
@@ -42,7 +42,7 @@ const PaneSlugPanel = ({ nodeId, setMode }: PaneSlugPanelProps) => {
|
|
|
42
42
|
//.replace(/^-+|-+$/g, '');
|
|
43
43
|
};
|
|
44
44
|
|
|
45
|
-
const handleSlugChange = (e:
|
|
45
|
+
const handleSlugChange = (e: ChangeEvent<HTMLInputElement>) => {
|
|
46
46
|
const newSlug = validateSlug(e.target.value);
|
|
47
47
|
if (newSlug.length <= 75) {
|
|
48
48
|
// Prevent more than 75 chars
|
|
@@ -103,6 +103,19 @@ const AddPaneCodeHookPanel = ({
|
|
|
103
103
|
parentId: '',
|
|
104
104
|
codeHookTarget: selected,
|
|
105
105
|
isContextPane: isContextPane,
|
|
106
|
+
...(selected === 'shopify-product-grid' ||
|
|
107
|
+
selected === 'shopify-service-list'
|
|
108
|
+
? {
|
|
109
|
+
codeHookPayload: {
|
|
110
|
+
options: JSON.stringify({
|
|
111
|
+
category: 'product|service',
|
|
112
|
+
group: '',
|
|
113
|
+
title: '',
|
|
114
|
+
bgColor: '#f9f9f9',
|
|
115
|
+
}),
|
|
116
|
+
},
|
|
117
|
+
}
|
|
118
|
+
: {}),
|
|
106
119
|
};
|
|
107
120
|
const targetId =
|
|
108
121
|
isStoryFragment || isContextPane
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState } from 'react';
|
|
1
|
+
import { useState, type ChangeEvent } from 'react';
|
|
2
2
|
|
|
3
3
|
interface AddPaneNewCustomCopyProps {
|
|
4
4
|
value: string;
|
|
@@ -11,7 +11,7 @@ export const AddPaneNewCustomCopy = ({
|
|
|
11
11
|
}: AddPaneNewCustomCopyProps) => {
|
|
12
12
|
const [localValue, setLocalValue] = useState(initialValue);
|
|
13
13
|
|
|
14
|
-
const handleChange = (e:
|
|
14
|
+
const handleChange = (e: ChangeEvent<HTMLTextAreaElement>) => {
|
|
15
15
|
setLocalValue(e.target.value);
|
|
16
16
|
};
|
|
17
17
|
|
|
@@ -302,7 +302,7 @@ const ConfigPanePanel = ({
|
|
|
302
302
|
{/* Right Aligned Tools */}
|
|
303
303
|
<div className="ml-auto flex items-center gap-2 px-2">
|
|
304
304
|
{/* Delete & Reorder Tools */}
|
|
305
|
-
{!isTemplate && !isContextPane &&
|
|
305
|
+
{!isTemplate && !isContextPane && (
|
|
306
306
|
<div className="flex items-center gap-1 border-r border-gray-300 pr-2">
|
|
307
307
|
<button
|
|
308
308
|
onClick={handleMoveUp}
|
|
@@ -71,7 +71,12 @@ const IconSelector = ({
|
|
|
71
71
|
() => createListCollection({ items: filteredIcons }),
|
|
72
72
|
[filteredIcons]
|
|
73
73
|
);
|
|
74
|
-
const iconSelectorStyles =
|
|
74
|
+
const iconSelectorStyles = `
|
|
75
|
+
.icon-item .icon-indicator { display: none; }
|
|
76
|
+
.icon-item[data-state="checked"] .icon-indicator { display: flex; }
|
|
77
|
+
.icon-item[data-highlighted] { background-color: #0891b2; color: #fff; }
|
|
78
|
+
.icon-item[data-highlighted] .icon-indicator { color: #fff; }
|
|
79
|
+
`;
|
|
75
80
|
return (
|
|
76
81
|
<div>
|
|
77
82
|
<style>{iconSelectorStyles}</style>
|
|
@@ -100,12 +105,12 @@ const IconSelector = ({
|
|
|
100
105
|
<Combobox.Item
|
|
101
106
|
key={icon}
|
|
102
107
|
item={icon}
|
|
103
|
-
className="icon-item relative cursor-pointer select-none py-2 pl-10 pr-4 text-gray-900
|
|
108
|
+
className="icon-item relative cursor-pointer select-none py-2 pl-10 pr-4 text-gray-900"
|
|
104
109
|
>
|
|
105
110
|
<Combobox.ItemText>
|
|
106
111
|
<i className={`bi bi-${icon} mr-2 text-lg`}></i> {icon}
|
|
107
112
|
</Combobox.ItemText>
|
|
108
|
-
<Combobox.ItemIndicator className="icon-indicator absolute inset-y-0 left-0 flex items-center pl-3 text-cyan-600
|
|
113
|
+
<Combobox.ItemIndicator className="icon-indicator absolute inset-y-0 left-0 flex items-center pl-3 text-cyan-600">
|
|
109
114
|
<CheckIcon className="h-5 w-5" />
|
|
110
115
|
</Combobox.ItemIndicator>
|
|
111
116
|
</Combobox.Item>
|