@dyrected/admin 2.5.47 → 2.5.48

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.
Files changed (3) hide show
  1. package/dist/admin.css +32 -119
  2. package/dist/index.mjs +359 -285
  3. package/package.json +4 -3
package/dist/admin.css CHANGED
@@ -1164,10 +1164,6 @@
1164
1164
  right: 1rem;
1165
1165
  }
1166
1166
 
1167
- .dy-right-\[12\%\]{
1168
- right: 12%;
1169
- }
1170
-
1171
1167
  .dy-top-0{
1172
1168
  top: 0px;
1173
1169
  }
@@ -1369,10 +1365,6 @@
1369
1365
  margin-bottom: 1rem;
1370
1366
  }
1371
1367
 
1372
- .dy-mb-5{
1373
- margin-bottom: 1.25rem;
1374
- }
1375
-
1376
1368
  .dy-mb-6{
1377
1369
  margin-bottom: 1.5rem;
1378
1370
  }
@@ -1658,6 +1650,10 @@
1658
1650
  max-height: 15rem;
1659
1651
  }
1660
1652
 
1653
+ .dy-max-h-64{
1654
+ max-height: 16rem;
1655
+ }
1656
+
1661
1657
  .dy-max-h-80{
1662
1658
  max-height: 20rem;
1663
1659
  }
@@ -1698,6 +1694,10 @@
1698
1694
  max-height: 42dvh;
1699
1695
  }
1700
1696
 
1697
+ .dy-max-h-\[60vh\]{
1698
+ max-height: 60vh;
1699
+ }
1700
+
1701
1701
  .dy-max-h-\[90dvh\]{
1702
1702
  max-height: 90dvh;
1703
1703
  }
@@ -1754,10 +1754,6 @@
1754
1754
  min-height: 220px;
1755
1755
  }
1756
1756
 
1757
- .dy-min-h-\[340px\]{
1758
- min-height: 340px;
1759
- }
1760
-
1761
1757
  .dy-min-h-\[400px\]{
1762
1758
  min-height: 400px;
1763
1759
  }
@@ -1790,10 +1786,6 @@
1790
1786
  width: 0.375rem;
1791
1787
  }
1792
1788
 
1793
- .dy-w-1\/3{
1794
- width: 33.333333%;
1795
- }
1796
-
1797
1789
  .dy-w-10{
1798
1790
  width: 2.5rem;
1799
1791
  }
@@ -2044,10 +2036,6 @@
2044
2036
  max-width: 150px;
2045
2037
  }
2046
2038
 
2047
- .dy-max-w-\[180px\]{
2048
- max-width: 180px;
2049
- }
2050
-
2051
2039
  .dy-max-w-full{
2052
2040
  max-width: 100%;
2053
2041
  }
@@ -2170,11 +2158,6 @@
2170
2158
  transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
2171
2159
  }
2172
2160
 
2173
- .dy-skew-x-\[-12deg\]{
2174
- --tw-skew-x: -12deg;
2175
- transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
2176
- }
2177
-
2178
2161
  .dy-scale-100{
2179
2162
  --tw-scale-x: 1;
2180
2163
  --tw-scale-y: 1;
@@ -2382,14 +2365,6 @@
2382
2365
  gap: 0.375rem;
2383
2366
  }
2384
2367
 
2385
- .dy-gap-10{
2386
- gap: 2.5rem;
2387
- }
2388
-
2389
- .dy-gap-12{
2390
- gap: 3rem;
2391
- }
2392
-
2393
2368
  .dy-gap-2{
2394
2369
  gap: 0.5rem;
2395
2370
  }
@@ -2440,6 +2415,12 @@
2440
2415
  row-gap: 1.5rem;
2441
2416
  }
2442
2417
 
2418
+ .dy-space-x-2 > :not([hidden]) ~ :not([hidden]){
2419
+ --tw-space-x-reverse: 0;
2420
+ margin-right: calc(0.5rem * var(--tw-space-x-reverse));
2421
+ margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse)));
2422
+ }
2423
+
2443
2424
  .dy-space-y-0 > :not([hidden]) ~ :not([hidden]){
2444
2425
  --tw-space-y-reverse: 0;
2445
2426
  margin-top: calc(0px * calc(1 - var(--tw-space-y-reverse)));
@@ -2464,6 +2445,12 @@
2464
2445
  margin-bottom: calc(0.375rem * var(--tw-space-y-reverse));
2465
2446
  }
2466
2447
 
2448
+ .dy-space-y-10 > :not([hidden]) ~ :not([hidden]){
2449
+ --tw-space-y-reverse: 0;
2450
+ margin-top: calc(2.5rem * calc(1 - var(--tw-space-y-reverse)));
2451
+ margin-bottom: calc(2.5rem * var(--tw-space-y-reverse));
2452
+ }
2453
+
2467
2454
  .dy-space-y-2 > :not([hidden]) ~ :not([hidden]){
2468
2455
  --tw-space-y-reverse: 0;
2469
2456
  margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));
@@ -2572,10 +2559,6 @@
2572
2559
  border-radius: 1.5rem;
2573
2560
  }
2574
2561
 
2575
- .dy-rounded-\[28px\]{
2576
- border-radius: 28px;
2577
- }
2578
-
2579
2562
  .dy-rounded-\[inherit\]{
2580
2563
  border-radius: inherit;
2581
2564
  }
@@ -2677,6 +2660,10 @@
2677
2660
  border-color: rgb(253 230 138 / var(--tw-border-opacity, 1));
2678
2661
  }
2679
2662
 
2663
+ .dy-border-amber-300\/60{
2664
+ border-color: rgb(252 211 77 / 0.6);
2665
+ }
2666
+
2680
2667
  .dy-border-blue-100{
2681
2668
  --tw-border-opacity: 1;
2682
2669
  border-color: rgb(219 234 254 / var(--tw-border-opacity, 1));
@@ -2854,6 +2841,10 @@
2854
2841
  background-color: rgb(245 158 11 / var(--tw-bg-opacity, 1));
2855
2842
  }
2856
2843
 
2844
+ .dy-bg-amber-500\/10{
2845
+ background-color: rgb(245 158 11 / 0.1);
2846
+ }
2847
+
2857
2848
  .dy-bg-amber-500\/5{
2858
2849
  background-color: rgb(245 158 11 / 0.05);
2859
2850
  }
@@ -3186,10 +3177,6 @@
3186
3177
  padding: 1.5rem;
3187
3178
  }
3188
3179
 
3189
- .dy-p-7{
3190
- padding: 1.75rem;
3191
- }
3192
-
3193
3180
  .dy-p-8{
3194
3181
  padding: 2rem;
3195
3182
  }
@@ -3455,11 +3442,6 @@
3455
3442
  line-height: 2.25rem;
3456
3443
  }
3457
3444
 
3458
- .dy-text-4xl{
3459
- font-size: 2.25rem;
3460
- line-height: 2.5rem;
3461
- }
3462
-
3463
3445
  .dy-text-\[0\.8rem\]{
3464
3446
  font-size: 0.8rem;
3465
3447
  }
@@ -3562,14 +3544,6 @@
3562
3544
  line-height: 1.5rem;
3563
3545
  }
3564
3546
 
3565
- .dy-leading-7{
3566
- line-height: 1.75rem;
3567
- }
3568
-
3569
- .dy-leading-\[0\.98\]{
3570
- line-height: 0.98;
3571
- }
3572
-
3573
3547
  .dy-leading-none{
3574
3548
  line-height: 1;
3575
3549
  }
@@ -3586,10 +3560,6 @@
3586
3560
  letter-spacing: 0.12em;
3587
3561
  }
3588
3562
 
3589
- .dy-tracking-\[0\.14em\]{
3590
- letter-spacing: 0.14em;
3591
- }
3592
-
3593
3563
  .dy-tracking-tight{
3594
3564
  letter-spacing: -0.025em;
3595
3565
  }
@@ -3836,6 +3806,10 @@
3836
3806
  text-underline-offset: 4px;
3837
3807
  }
3838
3808
 
3809
+ .dy-accent-amber-500{
3810
+ accent-color: #f59e0b;
3811
+ }
3812
+
3839
3813
  .dy-opacity-0{
3840
3814
  opacity: 0;
3841
3815
  }
@@ -4722,10 +4696,6 @@
4722
4696
  border-color: hsl(var(--border) / 0.8);
4723
4697
  }
4724
4698
 
4725
- .hover\:dy-border-foreground\/30:hover{
4726
- border-color: hsl(var(--foreground) / 0.3);
4727
- }
4728
-
4729
4699
  .hover\:dy-border-primary\/20:hover{
4730
4700
  border-color: hsl(var(--primary) / 0.2);
4731
4701
  }
@@ -4734,10 +4704,6 @@
4734
4704
  border-color: hsl(var(--primary) / 0.4);
4735
4705
  }
4736
4706
 
4737
- .hover\:dy-border-primary\/60:hover{
4738
- border-color: hsl(var(--primary) / 0.6);
4739
- }
4740
-
4741
4707
  .hover\:dy-bg-accent:hover{
4742
4708
  background-color: hsl(var(--accent));
4743
4709
  }
@@ -4794,10 +4760,6 @@
4794
4760
  background-color: hsl(var(--muted) / 0.3);
4795
4761
  }
4796
4762
 
4797
- .hover\:dy-bg-muted\/40:hover{
4798
- background-color: hsl(var(--muted) / 0.4);
4799
- }
4800
-
4801
4763
  .hover\:dy-bg-muted\/5:hover{
4802
4764
  background-color: hsl(var(--muted) / 0.05);
4803
4765
  }
@@ -4834,10 +4796,6 @@
4834
4796
  background-color: hsl(var(--primary) / 0.03);
4835
4797
  }
4836
4798
 
4837
- .hover\:dy-bg-primary\/\[0\.04\]:hover{
4838
- background-color: hsl(var(--primary) / 0.04);
4839
- }
4840
-
4841
4799
  .hover\:dy-bg-primary\/\[0\.06\]:hover{
4842
4800
  background-color: hsl(var(--primary) / 0.06);
4843
4801
  }
@@ -4858,10 +4816,6 @@
4858
4816
  color: hsl(var(--accent-foreground));
4859
4817
  }
4860
4818
 
4861
- .hover\:dy-text-card-foreground:hover{
4862
- color: hsl(var(--card-foreground));
4863
- }
4864
-
4865
4819
  .hover\:dy-text-destructive:hover{
4866
4820
  color: hsl(var(--destructive));
4867
4821
  }
@@ -5081,16 +5035,6 @@
5081
5035
  opacity: 0.6;
5082
5036
  }
5083
5037
 
5084
- .dy-group:hover .group-hover\:dy--translate-y-0\.5{
5085
- --tw-translate-y: -0.125rem;
5086
- transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
5087
- }
5088
-
5089
- .dy-group:hover .group-hover\:dy-translate-x-0\.5{
5090
- --tw-translate-x: 0.125rem;
5091
- transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
5092
- }
5093
-
5094
5038
  .dy-group:hover .group-hover\:dy-bg-primary\/10{
5095
5039
  background-color: hsl(var(--primary) / 0.1);
5096
5040
  }
@@ -5811,10 +5755,6 @@
5811
5755
  background-color: rgb(0 0 0 / 0.4);
5812
5756
  }
5813
5757
 
5814
- .sm\:dy-p-10{
5815
- padding: 2.5rem;
5816
- }
5817
-
5818
5758
  .sm\:dy-p-12{
5819
5759
  padding: 3rem;
5820
5760
  }
@@ -5880,21 +5820,11 @@
5880
5820
  line-height: 2.25rem;
5881
5821
  }
5882
5822
 
5883
- .sm\:dy-text-5xl{
5884
- font-size: 3rem;
5885
- line-height: 1;
5886
- }
5887
-
5888
5823
  .sm\:dy-text-base{
5889
5824
  font-size: 1rem;
5890
5825
  line-height: 1.5rem;
5891
5826
  }
5892
5827
 
5893
- .sm\:dy-text-lg{
5894
- font-size: 1.125rem;
5895
- line-height: 1.75rem;
5896
- }
5897
-
5898
5828
  .sm\:dy-text-xl{
5899
5829
  font-size: 1.25rem;
5900
5830
  line-height: 1.75rem;
@@ -6141,10 +6071,6 @@
6141
6071
  grid-template-columns: repeat(6, minmax(0, 1fr));
6142
6072
  }
6143
6073
 
6144
- .lg\:dy-grid-cols-\[1\.35fr_0\.65fr\]{
6145
- grid-template-columns: 1.35fr 0.65fr;
6146
- }
6147
-
6148
6074
  .lg\:dy-flex-row{
6149
6075
  flex-direction: row;
6150
6076
  }
@@ -6153,10 +6079,6 @@
6153
6079
  align-items: flex-end;
6154
6080
  }
6155
6081
 
6156
- .lg\:dy-justify-end{
6157
- justify-content: flex-end;
6158
- }
6159
-
6160
6082
  .lg\:dy-justify-between{
6161
6083
  justify-content: space-between;
6162
6084
  }
@@ -6179,10 +6101,6 @@
6179
6101
  margin-bottom: calc(2rem * var(--tw-space-y-reverse));
6180
6102
  }
6181
6103
 
6182
- .lg\:dy-p-12{
6183
- padding: 3rem;
6184
- }
6185
-
6186
6104
  .lg\:dy-px-6{
6187
6105
  padding-left: 1.5rem;
6188
6106
  padding-right: 1.5rem;
@@ -6202,11 +6120,6 @@
6202
6120
  padding-top: 2rem;
6203
6121
  padding-bottom: 2rem;
6204
6122
  }
6205
-
6206
- .lg\:dy-text-6xl{
6207
- font-size: 3.75rem;
6208
- line-height: 1;
6209
- }
6210
6123
  }
6211
6124
 
6212
6125
  @media (min-width: 1280px){
package/dist/index.mjs CHANGED
@@ -5,7 +5,7 @@ import { HashRouter, Link, MemoryRouter, Route, Routes, useLocation, useNavigate
5
5
  import { QueryClient, QueryClientProvider, useInfiniteQuery, useMutation, useQueries, useQuery, useQueryClient } from "@tanstack/react-query";
6
6
  import { createClient } from "@dyrected/sdk";
7
7
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
- import { AlertCircle, AlertTriangle, AlignCenter, AlignLeft, AlignRight, Archive, ArrowDown, ArrowLeft, ArrowRight, ArrowUp, ArrowUpRight, Bold, BookOpen, Braces, Calendar, Check, CheckCircle, CheckCircle2, ChevronDown, ChevronDownIcon, ChevronLeft, ChevronLeftIcon, ChevronRight, ChevronRightIcon, ChevronUp, ChevronsUpDown, Circle, Clock, Clock3, Code, Code2, Compass, Copy, Database, Download, ExternalLink, Eye, EyeOff, FileDown, FileIcon, FileText, FileUp, Filter, Globe, GripVertical, Heading1, Heading2, Image as Image$1, Info, Italic, KeyRound, Layers, LayoutDashboard, Library, Link as Link$1, List, ListOrdered, Loader2, Lock, LogOut, Mail, Menu, Monitor, Moon, MoreHorizontal, PanelLeftClose, PanelLeftOpen, Pencil, Play, Plus, Quote, RotateCcw, Save, Scissors, Search, Settings, Settings2, Share2, Shield, Smartphone, Sparkles, Strikethrough, Sun, Table, Trash2, Underline, Undo2, Upload, UploadCloud, Users, Video, Volume2, X, XCircle, icons } from "lucide-react";
8
+ import { AlertCircle, AlertTriangle, AlignCenter, AlignLeft, AlignRight, Archive, ArrowDown, ArrowLeft, ArrowRight, ArrowUp, ArrowUpRight, Bold, Braces, Calendar, Check, CheckCircle, CheckCircle2, ChevronDown, ChevronDownIcon, ChevronLeft, ChevronLeftIcon, ChevronRight, ChevronRightIcon, ChevronUp, ChevronsUpDown, Circle, Clock, Clock3, Code, Copy, Database, Download, ExternalLink, Eye, EyeOff, FileDown, FileIcon, FileText, FileUp, Filter, Globe, GripVertical, Heading1, Heading2, Image as Image$1, Info, Italic, KeyRound, Layers, LayoutDashboard, Library, Link as Link$1, List, ListOrdered, Loader2, Lock, LogOut, Mail, Menu, Monitor, Moon, MoreHorizontal, PanelLeftClose, PanelLeftOpen, Pencil, Play, Plus, Quote, RotateCcw, Save, Scissors, Search, Settings, Settings2, Share2, Shield, Smartphone, Sparkles, Strikethrough, Sun, Table, Trash2, Underline, Undo2, Upload, UploadCloud, Users, Video, Volume2, X, XCircle, icons } from "lucide-react";
9
9
  import { clsx } from "clsx";
10
10
  import { extendTailwindMerge } from "tailwind-merge";
11
11
  import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
@@ -19,13 +19,13 @@ import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
19
19
  import { DndContext, KeyboardSensor, PointerSensor, closestCenter, useSensor, useSensors } from "@dnd-kit/core";
20
20
  import { SortableContext, arrayMove, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy } from "@dnd-kit/sortable";
21
21
  import { CSS } from "@dnd-kit/utilities";
22
- import * as DialogPrimitive from "@radix-ui/react-dialog";
23
22
  import Papa from "papaparse";
24
23
  import * as ProgressPrimitive from "@radix-ui/react-progress";
25
24
  import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
26
25
  import jexl from "jexl";
27
26
  import { DataSheetGrid, checkboxColumn, keyColumn, textColumn } from "react-datasheet-grid";
28
27
  import "react-datasheet-grid/dist/style.css";
28
+ import * as SheetPrimitive from "@radix-ui/react-dialog";
29
29
  import { EditorContent, useEditor } from "@tiptap/react";
30
30
  import StarterKit from "@tiptap/starter-kit";
31
31
  import TextAlign from "@tiptap/extension-text-align";
@@ -50,12 +50,11 @@ import { DayPicker, getDefaultClassNames } from "react-day-picker";
50
50
  import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio";
51
51
  import * as SeparatorPrimitive from "@radix-ui/react-separator";
52
52
  import { Blurhash } from "react-blurhash";
53
+ import { GENERATE_CMS_PROMPT } from "@dyrected/knowledge";
53
54
  //#region src/providers/admin-auth.ts
54
55
  function getAdminCollectionSlug(schemas) {
55
56
  if (!schemas) return null;
56
- const requested = schemas.adminAuth?.collectionSlug;
57
- if (requested) return requested;
58
- return findCollection(schemas.collections, (collection) => collection.slug === "__admins")?.slug ?? findCollection(schemas.collections, (collection) => !!collection.auth)?.slug ?? null;
57
+ return findCollection(schemas.collections, (collection) => collection.slug === "__admins")?.slug ?? findCollection(schemas.collections, (collection) => collection.slug === schemas.adminAuth?.collectionSlug)?.slug ?? findCollection(schemas.collections, (collection) => !!collection.auth)?.slug ?? null;
59
58
  }
60
59
  function findCollection(collections, predicate) {
61
60
  return collections.find(predicate);
@@ -159,18 +158,12 @@ function DyrectedProvider({ children, apiKey: initialApiKey, baseUrl: initialBas
159
158
  schemas
160
159
  ]);
161
160
  const logout = useCallback(() => {
162
- localStorage.removeItem("dyrected_url");
163
- localStorage.removeItem("dyrected_key");
164
- localStorage.removeItem("dyrected_site_id");
165
161
  localStorage.removeItem("dyrected_token");
166
162
  localStorage.removeItem("dyrected_admin_auth_collection");
167
- setBaseUrl("");
168
- setApiKey(void 0);
169
- setSiteId(void 0);
163
+ if (client) client.clearToken();
170
164
  setAuthCollectionSlug(null);
171
165
  setUser(null);
172
- setSchemas(null);
173
- }, []);
166
+ }, [client]);
174
167
  return /* @__PURE__ */ jsx(DyrectedContext.Provider, {
175
168
  value: {
176
169
  client,
@@ -642,7 +635,7 @@ function ThemeSelector({ collapsed = false, mobile = false }) {
642
635
  const OptionIcon = option.icon;
643
636
  return /* @__PURE__ */ jsxs(DropdownMenuRadioItem, {
644
637
  value: option.value,
645
- className: "dy-cursor-pointer",
638
+ className: "dy-cursor-pointer dy-space-x-2",
646
639
  children: [/* @__PURE__ */ jsx(OptionIcon, { className: "dy-h-4 dy-w-4" }), option.label]
647
640
  }, option.value);
648
641
  })
@@ -941,7 +934,7 @@ function AdminShell({ children, isEmbedded = false }) {
941
934
  className: "dy-ml-auto dy-flex dy-items-center dy-gap-1.5",
942
935
  children: [/* @__PURE__ */ jsx(ThemeSelector, { mobile: true }), user && /* @__PURE__ */ jsx("div", {
943
936
  className: "dy-flex dy-h-8 dy-w-8 dy-items-center dy-justify-center dy-rounded-full dy-bg-primary/10 dy-text-primary dy-font-semibold dy-text-xs dy-shrink-0",
944
- children: (user.name || user.email || "?")[0].toUpperCase()
937
+ children: (user.name || user.email || "?").charAt(0).toUpperCase()
945
938
  })]
946
939
  })
947
940
  ]
@@ -2073,59 +2066,6 @@ var Checkbox = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__
2073
2066
  }));
2074
2067
  Checkbox.displayName = CheckboxPrimitive.Root.displayName;
2075
2068
  //#endregion
2076
- //#region src/components/ui/dialog.tsx
2077
- var Dialog = DialogPrimitive.Root;
2078
- var DialogTrigger = DialogPrimitive.Trigger;
2079
- var DialogPortal = DialogPrimitive.Portal;
2080
- var DialogOverlay = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(DialogPrimitive.Overlay, {
2081
- ref,
2082
- className: cn("dy-fixed dy-inset-0 dy-z-50 dy-bg-black/40 dy-backdrop-blur-[2px] data-[state=open]:dy-animate-in data-[state=closed]:dy-animate-out data-[state=closed]:dy-fade-out-0 data-[state=open]:dy-fade-in-0", className),
2083
- ...props
2084
- }));
2085
- DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
2086
- var DialogContent = React$1.forwardRef(({ className, children, ...props }, ref) => {
2087
- const { resolvedTheme, themeClassName } = useAdminTheme();
2088
- return /* @__PURE__ */ jsx(DialogPortal, { children: /* @__PURE__ */ jsxs("div", {
2089
- className: themeClassName,
2090
- "data-theme": resolvedTheme,
2091
- children: [/* @__PURE__ */ jsx(DialogOverlay, {}), /* @__PURE__ */ jsxs(DialogPrimitive.Content, {
2092
- ref,
2093
- className: cn("dy-fixed dy-left-[50%] dy-top-[50%] dy-z-50 dy-grid dy-w-full dy-max-w-lg dy-translate-x-[-50%] dy-translate-y-[-50%] dy-gap-4 dy-border dy-bg-background dy-p-6 dy-shadow-2xl dy-duration-200 data-[state=open]:dy-animate-in data-[state=closed]:dy-animate-out data-[state=closed]:dy-fade-out-0 data-[state=open]:dy-fade-in-0 data-[state=closed]:dy-zoom-out-95 data-[state=open]:dy-zoom-in-95 data-[state=closed]:dy-slide-out-to-left-1/2 data-[state=closed]:dy-slide-out-to-top-[48%] data-[state=open]:dy-slide-in-from-left-1/2 data-[state=open]:dy-slide-in-from-top-[48%] sm:dy-rounded-xl", className),
2094
- ...props,
2095
- children: [children, /* @__PURE__ */ jsxs(DialogPrimitive.Close, {
2096
- className: "dy-absolute dy-right-4 dy-top-4 dy-rounded-sm dy-opacity-70 dy-ring-offset-background dy-transition-opacity hover:dy-opacity-100 focus:dy-outline-none focus:dy-ring-2 focus:dy-ring-ring focus:dy-ring-offset-2 disabled:dy-pointer-events-none data-[state=open]:dy-bg-accent data-[state=open]:dy-text-muted-foreground",
2097
- children: [/* @__PURE__ */ jsx(X, { className: "dy-h-4 dy-w-4" }), /* @__PURE__ */ jsx("span", {
2098
- className: "dy-sr-only",
2099
- children: "Close"
2100
- })]
2101
- })]
2102
- })]
2103
- }) });
2104
- });
2105
- DialogContent.displayName = DialogPrimitive.Content.displayName;
2106
- var DialogHeader = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
2107
- className: cn("dy-flex dy-flex-col dy-space-y-1.5 dy-text-center sm:dy-text-left", className),
2108
- ...props
2109
- });
2110
- DialogHeader.displayName = "DialogHeader";
2111
- var DialogFooter = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
2112
- className: cn("dy-flex dy-flex-col-reverse sm:dy-flex-row sm:dy-justify-end sm:dy-space-x-2", className),
2113
- ...props
2114
- });
2115
- DialogFooter.displayName = "DialogFooter";
2116
- var DialogTitle = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(DialogPrimitive.Title, {
2117
- ref,
2118
- className: cn("dy-text-lg dy-font-semibold dy-leading-none dy-tracking-tight", className),
2119
- ...props
2120
- }));
2121
- DialogTitle.displayName = DialogPrimitive.Title.displayName;
2122
- var DialogDescription = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(DialogPrimitive.Description, {
2123
- ref,
2124
- className: cn("dy-text-sm dy-text-muted-foreground", className),
2125
- ...props
2126
- }));
2127
- DialogDescription.displayName = DialogPrimitive.Description.displayName;
2128
- //#endregion
2129
2069
  //#region src/components/ui/progress.tsx
2130
2070
  var Progress = React$1.forwardRef(({ className, value, ...props }, ref) => /* @__PURE__ */ jsx(ProgressPrimitive.Root, {
2131
2071
  ref,
@@ -2171,39 +2111,72 @@ function CsvImporter({ slug, schema, onClose }) {
2171
2111
  const [parsedRows, setParsedRows] = React$1.useState([]);
2172
2112
  const [mapping, setMapping] = React$1.useState({});
2173
2113
  const [validatedData, setValidatedData] = React$1.useState([]);
2114
+ const [isDragging, setIsDragging] = React$1.useState(false);
2115
+ const [fileError, setFileError] = React$1.useState(null);
2116
+ const [confirmedSkip, setConfirmedSkip] = React$1.useState(false);
2174
2117
  const [totalRows, setTotalRows] = React$1.useState(0);
2175
2118
  const [processedCount, setProcessedCount] = React$1.useState(0);
2176
2119
  const [successCount, setSuccessCount] = React$1.useState(0);
2177
2120
  const [failedRows, setFailedRows] = React$1.useState([]);
2121
+ const [retryableRows, setRetryableRows] = React$1.useState([]);
2178
2122
  const importableFields = React$1.useMemo(() => {
2179
2123
  return schema.fields.filter((f) => f.name !== "id" && f.name !== "createdAt" && f.name !== "updatedAt" && f.type !== "row" && f.type !== "join" && !f.admin?.hidden);
2180
2124
  }, [schema]);
2181
2125
  const requiredFields = React$1.useMemo(() => {
2182
2126
  return importableFields.filter((f) => f.required);
2183
2127
  }, [importableFields]);
2184
- const handleFileChange = (e) => {
2185
- const selectedFile = e.target.files?.[0];
2186
- if (!selectedFile) return;
2187
- Papa.parse(selectedFile, {
2128
+ const processFile = (file) => {
2129
+ setFileError(null);
2130
+ if (!(file.type === "text/csv" || file.name.toLowerCase().endsWith(".csv"))) {
2131
+ setFileError(`Unsupported file type: "${file.name}". Please upload a CSV file.`);
2132
+ return;
2133
+ }
2134
+ Papa.parse(file, {
2188
2135
  header: true,
2189
2136
  skipEmptyLines: "greedy",
2190
2137
  complete: (results) => {
2191
2138
  const headers = results.meta.fields || [];
2139
+ const rows = results.data;
2140
+ if (rows.length === 0) {
2141
+ setFileError("This CSV file has no importable rows. Please upload a file with at least one data row.");
2142
+ return;
2143
+ }
2192
2144
  setCsvHeaders(headers);
2193
- setParsedRows(results.data);
2145
+ setParsedRows(rows);
2194
2146
  const initialMapping = {};
2195
2147
  headers.forEach((header) => {
2196
- const match = importableFields.find((f) => f.name.toLowerCase() === header.toLowerCase() || f.label?.toLowerCase() === header.toLowerCase());
2197
- initialMapping[header] = match ? match.name : "__ignore__";
2148
+ initialMapping[header] = importableFields.find((f) => f.name?.toLowerCase() === header.toLowerCase() || f.label?.toLowerCase() === header.toLowerCase())?.name ?? "__ignore__";
2198
2149
  });
2199
2150
  setMapping(initialMapping);
2200
2151
  setStep("map");
2201
2152
  },
2202
2153
  error: (error) => {
2203
- console.error("PapaParse error:", error);
2154
+ setFileError(`Failed to parse CSV: ${error.message}`);
2204
2155
  }
2205
2156
  });
2206
2157
  };
2158
+ const handleFileChange = (e) => {
2159
+ const selectedFile = e.target.files?.[0];
2160
+ if (selectedFile) processFile(selectedFile);
2161
+ e.target.value = "";
2162
+ };
2163
+ const handleDragOver = (e) => {
2164
+ e.preventDefault();
2165
+ e.stopPropagation();
2166
+ setIsDragging(true);
2167
+ };
2168
+ const handleDragLeave = (e) => {
2169
+ e.preventDefault();
2170
+ e.stopPropagation();
2171
+ setIsDragging(false);
2172
+ };
2173
+ const handleDrop = (e) => {
2174
+ e.preventDefault();
2175
+ e.stopPropagation();
2176
+ setIsDragging(false);
2177
+ const file = e.dataTransfer.files?.[0];
2178
+ if (file) processFile(file);
2179
+ };
2207
2180
  const handleMapChange = (header, fieldName) => {
2208
2181
  setMapping((prev) => ({
2209
2182
  ...prev,
@@ -2318,18 +2291,21 @@ function CsvImporter({ slug, schema, onClose }) {
2318
2291
  isValid
2319
2292
  };
2320
2293
  }));
2294
+ setConfirmedSkip(false);
2321
2295
  setStep("preview");
2322
2296
  };
2323
- const startImport = async () => {
2297
+ const startImport = async (rows = validatedData) => {
2324
2298
  setStep("importing");
2325
- setTotalRows(validatedData.length);
2299
+ setTotalRows(rows.length);
2326
2300
  setProcessedCount(0);
2327
2301
  setSuccessCount(0);
2328
2302
  setFailedRows([]);
2303
+ setRetryableRows([]);
2329
2304
  let success = 0;
2330
2305
  const failures = [];
2331
- for (let i = 0; i < validatedData.length; i++) {
2332
- const rowResult = validatedData[i];
2306
+ const apiFailures = [];
2307
+ for (let i = 0; i < rows.length; i++) {
2308
+ const rowResult = rows[i];
2333
2309
  setProcessedCount(i + 1);
2334
2310
  if (!rowResult.isValid) {
2335
2311
  failures.push({
@@ -2359,17 +2335,24 @@ function CsvImporter({ slug, schema, onClose }) {
2359
2335
  success++;
2360
2336
  setSuccessCount(success);
2361
2337
  } catch (error) {
2338
+ const message = error.message || "Failed to create entry";
2362
2339
  failures.push({
2363
2340
  row: rowResult.rowNumber,
2364
2341
  data: rowResult.data,
2365
- error: error.message || "Failed to create entry"
2342
+ error: message
2366
2343
  });
2367
2344
  setFailedRows([...failures]);
2345
+ apiFailures.push(rowResult);
2368
2346
  }
2369
2347
  }
2348
+ setRetryableRows(apiFailures);
2370
2349
  queryClient.invalidateQueries({ queryKey: ["collection", slug] });
2371
2350
  setStep("complete");
2372
2351
  };
2352
+ const handleRetryFailed = () => {
2353
+ setValidatedData(retryableRows);
2354
+ startImport(retryableRows);
2355
+ };
2373
2356
  const downloadFailedCsv = () => {
2374
2357
  if (failedRows.length === 0) return;
2375
2358
  const headers = [...csvHeaders, "Import Error"];
@@ -2401,14 +2384,17 @@ function CsvImporter({ slug, schema, onClose }) {
2401
2384
  return /* @__PURE__ */ jsxs("div", {
2402
2385
  className: "dy-space-y-6",
2403
2386
  children: [
2404
- step === "upload" && /* @__PURE__ */ jsx("div", {
2387
+ step === "upload" && /* @__PURE__ */ jsxs("div", {
2405
2388
  className: "dy-space-y-4",
2406
- children: /* @__PURE__ */ jsx("div", {
2407
- className: "dy-text-center dy-py-10 dy-border-2 dy-border-dashed dy-border-border dy-rounded-xl hover:dy-bg-muted/30 dy-transition-colors",
2389
+ children: [/* @__PURE__ */ jsx("div", {
2390
+ className: cn("dy-text-center dy-py-10 dy-border-2 dy-border-dashed dy-rounded-xl dy-transition-colors", isDragging ? "dy-border-primary dy-bg-primary/5" : "dy-border-border hover:dy-bg-muted/30"),
2391
+ onDragOver: handleDragOver,
2392
+ onDragLeave: handleDragLeave,
2393
+ onDrop: handleDrop,
2408
2394
  children: /* @__PURE__ */ jsxs("label", {
2409
2395
  className: "dy-cursor-pointer dy-block dy-space-y-4 dy-px-6",
2410
2396
  children: [
2411
- /* @__PURE__ */ jsx(Upload, { className: "dy-h-10 dy-w-10 dy-mx-auto dy-text-muted-foreground" }),
2397
+ /* @__PURE__ */ jsx(Upload, { className: cn("dy-h-10 dy-w-10 dy-mx-auto", isDragging ? "dy-text-primary" : "dy-text-muted-foreground") }),
2412
2398
  /* @__PURE__ */ jsxs("div", {
2413
2399
  className: "dy-space-y-1",
2414
2400
  children: [/* @__PURE__ */ jsx("p", {
@@ -2427,7 +2413,10 @@ function CsvImporter({ slug, schema, onClose }) {
2427
2413
  })
2428
2414
  ]
2429
2415
  })
2430
- })
2416
+ }), fileError && /* @__PURE__ */ jsxs("div", {
2417
+ className: "dy-flex dy-items-center dy-gap-2 dy-p-3 dy-rounded-lg dy-bg-destructive/10 dy-border dy-border-destructive/20 dy-text-destructive dy-text-sm",
2418
+ children: [/* @__PURE__ */ jsx(AlertCircle, { className: "dy-h-4 dy-w-4 dy-shrink-0" }), fileError]
2419
+ })]
2431
2420
  }),
2432
2421
  step === "map" && /* @__PURE__ */ jsxs("div", {
2433
2422
  className: "dy-space-y-4",
@@ -2531,19 +2520,22 @@ function CsvImporter({ slug, schema, onClose }) {
2531
2520
  })]
2532
2521
  }),
2533
2522
  /* @__PURE__ */ jsx("div", {
2534
- className: "dy-h-[300px] dy-overflow-auto dy-border dy-border-border dy-rounded-xl",
2523
+ className: "dy-overflow-x-auto dy-overflow-y-auto dy-max-h-[60vh] dy-border dy-border-border dy-rounded-xl",
2535
2524
  children: /* @__PURE__ */ jsxs("table", {
2536
- className: "dy-w-full dy-min-w-max dy-text-left dy-border-collapse",
2537
- children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", {
2538
- className: "dy-border-b dy-border-border dy-bg-muted/40 dy-text-xs dy-font-semibold dy-text-muted-foreground",
2539
- children: [/* @__PURE__ */ jsx("th", {
2540
- className: "dy-p-3 dy-w-16",
2541
- children: "Row"
2542
- }), importableFields.filter((f) => Object.values(mapping).includes(f.name)).map((f) => /* @__PURE__ */ jsx("th", {
2543
- className: "dy-p-3",
2544
- children: f.label || f.name
2545
- }, f.name))]
2546
- }) }), /* @__PURE__ */ jsx("tbody", {
2525
+ className: "dy-min-w-max dy-w-full dy-text-left dy-border-collapse",
2526
+ children: [/* @__PURE__ */ jsx("thead", {
2527
+ className: "dy-sticky dy-top-0 dy-z-10",
2528
+ children: /* @__PURE__ */ jsxs("tr", {
2529
+ className: "dy-border-b dy-border-border dy-bg-muted/40 dy-text-xs dy-font-semibold dy-text-muted-foreground",
2530
+ children: [/* @__PURE__ */ jsx("th", {
2531
+ className: "dy-p-3 dy-w-16",
2532
+ children: "Row"
2533
+ }), importableFields.filter((f) => Object.values(mapping).includes(f.name)).map((f) => /* @__PURE__ */ jsx("th", {
2534
+ className: "dy-p-3",
2535
+ children: f.label || f.name
2536
+ }, f.name))]
2537
+ })
2538
+ }), /* @__PURE__ */ jsx("tbody", {
2547
2539
  className: "dy-text-sm",
2548
2540
  children: previewRows.map((rowResult) => /* @__PURE__ */ jsxs("tr", {
2549
2541
  className: "dy-border-b dy-border-border hover:dy-bg-muted/20",
@@ -2565,6 +2557,39 @@ function CsvImporter({ slug, schema, onClose }) {
2565
2557
  })]
2566
2558
  })
2567
2559
  }),
2560
+ totalErrors > 0 && totalErrors < validatedData.length && /* @__PURE__ */ jsxs("label", {
2561
+ className: "dy-flex dy-items-start dy-gap-3 dy-p-3 dy-rounded-lg dy-border dy-border-amber-300/60 dy-bg-amber-500/10 dy-cursor-pointer",
2562
+ children: [/* @__PURE__ */ jsx("input", {
2563
+ type: "checkbox",
2564
+ className: "dy-mt-0.5 dy-accent-amber-500",
2565
+ checked: confirmedSkip,
2566
+ onChange: (e) => setConfirmedSkip(e.target.checked)
2567
+ }), /* @__PURE__ */ jsxs("span", {
2568
+ className: "dy-text-xs dy-text-amber-700 dark:dy-text-amber-400",
2569
+ children: [
2570
+ "I understand that ",
2571
+ /* @__PURE__ */ jsxs("strong", { children: [
2572
+ totalErrors,
2573
+ " row",
2574
+ totalErrors !== 1 ? "s" : ""
2575
+ ] }),
2576
+ " with validation errors will be skipped. Only the ",
2577
+ validatedData.length - totalErrors,
2578
+ " valid row",
2579
+ validatedData.length - totalErrors !== 1 ? "s" : "",
2580
+ " will be imported."
2581
+ ]
2582
+ })]
2583
+ }),
2584
+ totalErrors === validatedData.length && /* @__PURE__ */ jsxs("div", {
2585
+ className: "dy-flex dy-items-center dy-gap-2 dy-p-3 dy-rounded-lg dy-bg-destructive/10 dy-border dy-border-destructive/20 dy-text-destructive dy-text-sm",
2586
+ children: [
2587
+ /* @__PURE__ */ jsx(AlertCircle, { className: "dy-h-4 dy-w-4 dy-shrink-0" }),
2588
+ "All ",
2589
+ totalErrors,
2590
+ " rows have validation errors. Fix your CSV and re-upload before importing."
2591
+ ]
2592
+ }),
2568
2593
  /* @__PURE__ */ jsxs("div", {
2569
2594
  className: "dy-flex dy-justify-between dy-pt-4",
2570
2595
  children: [/* @__PURE__ */ jsx(Button, {
@@ -2572,14 +2597,17 @@ function CsvImporter({ slug, schema, onClose }) {
2572
2597
  onClick: () => setStep("map"),
2573
2598
  children: "Back"
2574
2599
  }), /* @__PURE__ */ jsxs(Button, {
2575
- onClick: startImport,
2600
+ onClick: () => startImport(),
2576
2601
  variant: "default",
2577
2602
  className: "dy-gap-2",
2603
+ disabled: totalErrors === validatedData.length || totalErrors > 0 && !confirmedSkip,
2578
2604
  children: [
2579
2605
  /* @__PURE__ */ jsx(Play, { className: "dy-h-4 dy-w-4" }),
2580
2606
  " Start Import (",
2581
2607
  validatedData.length - totalErrors,
2582
- " Rows)"
2608
+ " Row",
2609
+ validatedData.length - totalErrors !== 1 ? "s" : "",
2610
+ ")"
2583
2611
  ]
2584
2612
  })]
2585
2613
  })
@@ -2657,12 +2685,27 @@ function CsvImporter({ slug, schema, onClose }) {
2657
2685
  failedRows.length,
2658
2686
  " rows)"
2659
2687
  ]
2660
- }), /* @__PURE__ */ jsxs(Button, {
2661
- size: "sm",
2662
- variant: "outline",
2663
- className: "dy-h-8 dy-text-xs dy-gap-1.5",
2664
- onClick: downloadFailedCsv,
2665
- children: [/* @__PURE__ */ jsx(Download, { className: "dy-h-3.5 dy-w-3.5" }), " Download Errors CSV"]
2688
+ }), /* @__PURE__ */ jsxs("div", {
2689
+ className: "dy-flex dy-items-center dy-gap-2",
2690
+ children: [retryableRows.length > 0 && /* @__PURE__ */ jsxs(Button, {
2691
+ size: "sm",
2692
+ variant: "outline",
2693
+ className: "dy-h-8 dy-text-xs dy-gap-1.5",
2694
+ onClick: handleRetryFailed,
2695
+ children: [
2696
+ /* @__PURE__ */ jsx(RotateCcw, { className: "dy-h-3.5 dy-w-3.5" }),
2697
+ " Retry ",
2698
+ retryableRows.length,
2699
+ " Failed Row",
2700
+ retryableRows.length !== 1 ? "s" : ""
2701
+ ]
2702
+ }), /* @__PURE__ */ jsxs(Button, {
2703
+ size: "sm",
2704
+ variant: "outline",
2705
+ className: "dy-h-8 dy-text-xs dy-gap-1.5",
2706
+ onClick: downloadFailedCsv,
2707
+ children: [/* @__PURE__ */ jsx(Download, { className: "dy-h-3.5 dy-w-3.5" }), " Download Errors CSV"]
2708
+ })]
2666
2709
  })]
2667
2710
  }), /* @__PURE__ */ jsx(ScrollArea, {
2668
2711
  className: "dy-h-[180px] dy-border dy-border-border dy-rounded-xl",
@@ -2707,27 +2750,6 @@ function CsvImporter({ slug, schema, onClose }) {
2707
2750
  });
2708
2751
  }
2709
2752
  //#endregion
2710
- //#region src/components/ui/csv-importer-dialog.tsx
2711
- function CsvImporterDialog({ open, onOpenChange, slug, schema }) {
2712
- const title = schema.labels?.singular || schema.slug || slug;
2713
- return /* @__PURE__ */ jsx(Dialog, {
2714
- open,
2715
- onOpenChange,
2716
- children: /* @__PURE__ */ jsxs(DialogContent, {
2717
- className: "sm:dy-max-w-2xl",
2718
- children: [/* @__PURE__ */ jsxs(DialogHeader, { children: [/* @__PURE__ */ jsx(DialogTitle, { children: "Import CSV Data" }), /* @__PURE__ */ jsxs(DialogDescription, { children: [
2719
- "Import records into the ",
2720
- title,
2721
- " collection."
2722
- ] })] }), /* @__PURE__ */ jsx(CsvImporter, {
2723
- slug,
2724
- schema,
2725
- onClose: () => onOpenChange(false)
2726
- })]
2727
- })
2728
- });
2729
- }
2730
- //#endregion
2731
2753
  //#region src/components/ui/render-cell.tsx
2732
2754
  function RenderCell({ value, field, client, schemas }) {
2733
2755
  if (value === null || value === void 0) return /* @__PURE__ */ jsx("span", {
@@ -2943,14 +2965,14 @@ function MediaGrid({ items, baseUrl, onDelete, slug }) {
2943
2965
  }
2944
2966
  //#endregion
2945
2967
  //#region src/components/ui/sheet.tsx
2946
- var Sheet = DialogPrimitive.Root;
2947
- var SheetPortal = DialogPrimitive.Portal;
2948
- var SheetOverlay = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(DialogPrimitive.Overlay, {
2968
+ var Sheet = SheetPrimitive.Root;
2969
+ var SheetPortal = SheetPrimitive.Portal;
2970
+ var SheetOverlay = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(SheetPrimitive.Overlay, {
2949
2971
  className: cn("dy-fixed dy-inset-0 dy-z-50 dy-bg-black/40 dy-backdrop-blur-[2px] data-[state=open]:dy-animate-in data-[state=closed]:dy-animate-out data-[state=closed]:dy-fade-out-0 data-[state=open]:dy-fade-in-0", className),
2950
2972
  ...props,
2951
2973
  ref
2952
2974
  }));
2953
- SheetOverlay.displayName = DialogPrimitive.Overlay.displayName;
2975
+ SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
2954
2976
  var sheetVariants = cva("dy-fixed dy-z-50 dy-gap-4 dy-bg-background dy-p-6 dy-shadow-2xl dy-transition dy-ease-in-out data-[state=open]:dy-animate-in data-[state=closed]:dy-animate-out data-[state=closed]:dy-duration-300 data-[state=open]:dy-duration-500", {
2955
2977
  variants: { side: {
2956
2978
  top: "dy-inset-x-0 dy-top-0 dy-border-b data-[state=closed]:dy-slide-out-to-top data-[state=open]:dy-slide-in-from-top",
@@ -2965,11 +2987,11 @@ var SheetContent = React$1.forwardRef(({ side = "right", className, children, ..
2965
2987
  return /* @__PURE__ */ jsx(SheetPortal, { children: /* @__PURE__ */ jsxs("div", {
2966
2988
  className: themeClassName,
2967
2989
  "data-theme": resolvedTheme,
2968
- children: [/* @__PURE__ */ jsx(SheetOverlay, {}), /* @__PURE__ */ jsxs(DialogPrimitive.Content, {
2990
+ children: [/* @__PURE__ */ jsx(SheetOverlay, {}), /* @__PURE__ */ jsxs(SheetPrimitive.Content, {
2969
2991
  ref,
2970
2992
  className: cn(sheetVariants({ side }), className),
2971
2993
  ...props,
2972
- children: [children, /* @__PURE__ */ jsxs(DialogPrimitive.Close, {
2994
+ children: [children, /* @__PURE__ */ jsxs(SheetPrimitive.Close, {
2973
2995
  className: "dy-absolute dy-right-4 dy-top-4 dy-rounded-sm dy-opacity-70 dy-ring-offset-background dy-transition-opacity hover:dy-opacity-100 focus:dy-outline-none focus:dy-ring-2 focus:dy-ring-ring focus:dy-ring-offset-2 disabled:dy-pointer-events-none data-[state=open]:dy-bg-secondary",
2974
2996
  children: [/* @__PURE__ */ jsx(X, { className: "dy-h-4 dy-w-4" }), /* @__PURE__ */ jsx("span", {
2975
2997
  className: "dy-sr-only",
@@ -2979,7 +3001,7 @@ var SheetContent = React$1.forwardRef(({ side = "right", className, children, ..
2979
3001
  })]
2980
3002
  }) });
2981
3003
  });
2982
- SheetContent.displayName = DialogPrimitive.Content.displayName;
3004
+ SheetContent.displayName = SheetPrimitive.Content.displayName;
2983
3005
  var SheetHeader = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
2984
3006
  className: cn("dy-flex dy-flex-col dy-space-y-2 dy-text-center sm:dy-text-left", className),
2985
3007
  ...props
@@ -2990,18 +3012,18 @@ var SheetFooter = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
2990
3012
  ...props
2991
3013
  });
2992
3014
  SheetFooter.displayName = "SheetFooter";
2993
- var SheetTitle = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(DialogPrimitive.Title, {
3015
+ var SheetTitle = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(SheetPrimitive.Title, {
2994
3016
  ref,
2995
3017
  className: cn("dy-text-lg dy-font-semibold dy-text-foreground", className),
2996
3018
  ...props
2997
3019
  }));
2998
- SheetTitle.displayName = DialogPrimitive.Title.displayName;
2999
- var SheetDescription = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(DialogPrimitive.Description, {
3020
+ SheetTitle.displayName = SheetPrimitive.Title.displayName;
3021
+ var SheetDescription = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(SheetPrimitive.Description, {
3000
3022
  ref,
3001
3023
  className: cn("dy-text-sm dy-text-muted-foreground", className),
3002
3024
  ...props
3003
3025
  }));
3004
- SheetDescription.displayName = DialogPrimitive.Description.displayName;
3026
+ SheetDescription.displayName = SheetPrimitive.Description.displayName;
3005
3027
  //#endregion
3006
3028
  //#region src/components/ui/toggle.tsx
3007
3029
  var toggleVariants = cva("dy-inline-flex dy-items-center dy-justify-center dy-rounded-md dy-text-sm dy-font-medium dy-ring-offset-background dy-transition-colors hover:dy-bg-muted hover:dy-text-muted-foreground focus-visible:dy-outline-none focus-visible:dy-ring-2 focus-visible:dy-ring-ring focus-visible:dy-ring-offset-2 disabled:dy-pointer-events-none disabled:dy-opacity-50 data-[state=on]:dy-bg-accent data-[state=on]:dy-text-accent-foreground [&_svg]:dy-pointer-events-none [&_svg]:dy-size-4 [&_svg]:dy-shrink-0 dy-gap-2", {
@@ -3032,6 +3054,59 @@ var Toggle = React$1.forwardRef(({ className, variant, size, ...props }, ref) =>
3032
3054
  }));
3033
3055
  Toggle.displayName = TogglePrimitive.Root.displayName;
3034
3056
  //#endregion
3057
+ //#region src/components/ui/dialog.tsx
3058
+ var Dialog = SheetPrimitive.Root;
3059
+ var DialogTrigger = SheetPrimitive.Trigger;
3060
+ var DialogPortal = SheetPrimitive.Portal;
3061
+ var DialogOverlay = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(SheetPrimitive.Overlay, {
3062
+ ref,
3063
+ className: cn("dy-fixed dy-inset-0 dy-z-50 dy-bg-black/40 dy-backdrop-blur-[2px] data-[state=open]:dy-animate-in data-[state=closed]:dy-animate-out data-[state=closed]:dy-fade-out-0 data-[state=open]:dy-fade-in-0", className),
3064
+ ...props
3065
+ }));
3066
+ DialogOverlay.displayName = SheetPrimitive.Overlay.displayName;
3067
+ var DialogContent = React$1.forwardRef(({ className, children, ...props }, ref) => {
3068
+ const { resolvedTheme, themeClassName } = useAdminTheme();
3069
+ return /* @__PURE__ */ jsx(DialogPortal, { children: /* @__PURE__ */ jsxs("div", {
3070
+ className: themeClassName,
3071
+ "data-theme": resolvedTheme,
3072
+ children: [/* @__PURE__ */ jsx(DialogOverlay, {}), /* @__PURE__ */ jsxs(SheetPrimitive.Content, {
3073
+ ref,
3074
+ className: cn("dy-fixed dy-left-[50%] dy-top-[50%] dy-z-50 dy-grid dy-w-full dy-max-w-lg dy-translate-x-[-50%] dy-translate-y-[-50%] dy-gap-4 dy-border dy-bg-background dy-p-6 dy-shadow-2xl dy-duration-200 data-[state=open]:dy-animate-in data-[state=closed]:dy-animate-out data-[state=closed]:dy-fade-out-0 data-[state=open]:dy-fade-in-0 data-[state=closed]:dy-zoom-out-95 data-[state=open]:dy-zoom-in-95 data-[state=closed]:dy-slide-out-to-left-1/2 data-[state=closed]:dy-slide-out-to-top-[48%] data-[state=open]:dy-slide-in-from-left-1/2 data-[state=open]:dy-slide-in-from-top-[48%] sm:dy-rounded-xl", className),
3075
+ ...props,
3076
+ children: [children, /* @__PURE__ */ jsxs(SheetPrimitive.Close, {
3077
+ className: "dy-absolute dy-right-4 dy-top-4 dy-rounded-sm dy-opacity-70 dy-ring-offset-background dy-transition-opacity hover:dy-opacity-100 focus:dy-outline-none focus:dy-ring-2 focus:dy-ring-ring focus:dy-ring-offset-2 disabled:dy-pointer-events-none data-[state=open]:dy-bg-accent data-[state=open]:dy-text-muted-foreground",
3078
+ children: [/* @__PURE__ */ jsx(X, { className: "dy-h-4 dy-w-4" }), /* @__PURE__ */ jsx("span", {
3079
+ className: "dy-sr-only",
3080
+ children: "Close"
3081
+ })]
3082
+ })]
3083
+ })]
3084
+ }) });
3085
+ });
3086
+ DialogContent.displayName = SheetPrimitive.Content.displayName;
3087
+ var DialogHeader = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
3088
+ className: cn("dy-flex dy-flex-col dy-space-y-1.5 dy-text-center sm:dy-text-left", className),
3089
+ ...props
3090
+ });
3091
+ DialogHeader.displayName = "DialogHeader";
3092
+ var DialogFooter = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
3093
+ className: cn("dy-flex dy-flex-col-reverse sm:dy-flex-row sm:dy-justify-end sm:dy-space-x-2", className),
3094
+ ...props
3095
+ });
3096
+ DialogFooter.displayName = "DialogFooter";
3097
+ var DialogTitle = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(SheetPrimitive.Title, {
3098
+ ref,
3099
+ className: cn("dy-text-lg dy-font-semibold dy-leading-none dy-tracking-tight", className),
3100
+ ...props
3101
+ }));
3102
+ DialogTitle.displayName = SheetPrimitive.Title.displayName;
3103
+ var DialogDescription = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(SheetPrimitive.Description, {
3104
+ ref,
3105
+ className: cn("dy-text-sm dy-text-muted-foreground", className),
3106
+ ...props
3107
+ }));
3108
+ DialogDescription.displayName = SheetPrimitive.Description.displayName;
3109
+ //#endregion
3035
3110
  //#region src/components/ui/tabs.tsx
3036
3111
  var Tabs = TabsPrimitive.Root;
3037
3112
  var TabsList = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(TabsPrimitive.List, {
@@ -9706,7 +9781,7 @@ function CollectionListPage({ slug }) {
9706
9781
  const allAvailableColumns = React$1.useMemo(() => {
9707
9782
  if (!schema) return [];
9708
9783
  return [
9709
- ...schema.fields.filter((f) => f.name !== "password" && !f.admin?.hidden && f.type !== "row" && f.type !== "join").map((field) => field.name),
9784
+ ...schema.fields.filter((f) => f.name && f.name !== "password" && !f.admin?.hidden && f.type !== "row" && f.type !== "join").map((field) => field.name),
9710
9785
  "id",
9711
9786
  "createdAt",
9712
9787
  "updatedAt"
@@ -9714,7 +9789,7 @@ function CollectionListPage({ slug }) {
9714
9789
  }, [schema]);
9715
9790
  const defaultListColumns = React$1.useMemo(() => {
9716
9791
  if (!schema) return [];
9717
- const allDisplayFields = schema.fields.filter((f) => f.name !== "password" && !f.admin?.hidden && f.type !== "row" && f.type !== "join");
9792
+ const allDisplayFields = schema.fields.filter((f) => f.name && f.name !== "password" && !f.admin?.hidden && f.type !== "row" && f.type !== "join");
9718
9793
  const configuredColumns = Array.isArray(schema.admin?.defaultColumns) ? schema.admin.defaultColumns : [];
9719
9794
  return configuredColumns.length > 0 ? configuredColumns : allDisplayFields.slice(0, 3).map((field) => field.name);
9720
9795
  }, [schema]);
@@ -9913,7 +9988,7 @@ function CollectionListPage({ slug }) {
9913
9988
  key: "id",
9914
9989
  label: "ID"
9915
9990
  },
9916
- ...schema.fields.filter((f) => f.name !== "password" && !f.admin?.hidden && f.type !== "row" && f.type !== "join").map((f) => ({
9991
+ ...schema.fields.filter((f) => f.name !== "password" && !f.admin?.hidden && f.type !== "row" && f.type !== "join").filter((f) => !!f.name).map((f) => ({
9917
9992
  key: f.name,
9918
9993
  label: f.label || f.name
9919
9994
  })),
@@ -9988,7 +10063,7 @@ function CollectionListPage({ slug }) {
9988
10063
  }
9989
10064
  const columns = React$1.useMemo(() => {
9990
10065
  if (!schema) return [];
9991
- const allDisplayFields = schema.fields.filter((f) => f.name !== "password" && !f.admin?.hidden && f.type !== "row" && f.type !== "join");
10066
+ const allDisplayFields = schema.fields.filter((f) => f.name && f.name !== "password" && !f.admin?.hidden && f.type !== "row" && f.type !== "join");
9992
10067
  const fieldByName = new Map(allDisplayFields.map((field) => [field.name, field]));
9993
10068
  const configuredColumns = localPreference.columns.filter((col) => col.visible).map((col) => col.name);
9994
10069
  const visibleColumnNames = configuredColumns.length > 0 ? configuredColumns : allDisplayFields.slice(0, 3).map((field) => field.name);
@@ -10238,6 +10313,38 @@ function CollectionListPage({ slug }) {
10238
10313
  })
10239
10314
  ]
10240
10315
  });
10316
+ if (isImportOpen && schema) {
10317
+ const collectionTitle = schema.labels?.plural || schema.slug;
10318
+ return /* @__PURE__ */ jsxs("div", {
10319
+ className: "dy-space-y-6 dy-animate-in lg:dy-space-y-8",
10320
+ children: [
10321
+ /* @__PURE__ */ jsx("div", {
10322
+ className: "dy-flex dy-items-center dy-gap-3",
10323
+ children: /* @__PURE__ */ jsxs(Button, {
10324
+ variant: "ghost",
10325
+ size: "sm",
10326
+ className: "dy-h-8 dy-px-2 dy-gap-1.5 dy-text-xs dy-text-muted-foreground hover:dy-text-foreground",
10327
+ onClick: () => setIsImportOpen(false),
10328
+ children: [
10329
+ /* @__PURE__ */ jsx(ArrowLeft, { className: "dy-h-3.5 dy-w-3.5" }),
10330
+ "Back to ",
10331
+ collectionTitle
10332
+ ]
10333
+ })
10334
+ }),
10335
+ /* @__PURE__ */ jsx(PageHeader, {
10336
+ title: `Import CSV — ${collectionTitle}`,
10337
+ description: `Upload a CSV file to bulk-import records into the ${collectionTitle} collection.`,
10338
+ icon: FileUp
10339
+ }),
10340
+ /* @__PURE__ */ jsx(CsvImporter, {
10341
+ slug,
10342
+ schema,
10343
+ onClose: () => setIsImportOpen(false)
10344
+ })
10345
+ ]
10346
+ });
10347
+ }
10241
10348
  return /* @__PURE__ */ jsxs("div", {
10242
10349
  className: "dy-space-y-6 dy-animate-in lg:dy-space-y-8",
10243
10350
  children: [
@@ -10511,12 +10618,6 @@ function CollectionListPage({ slug }) {
10511
10618
  componentProps: collectionComponentProps
10512
10619
  })
10513
10620
  ]
10514
- }),
10515
- /* @__PURE__ */ jsx(CsvImporterDialog, {
10516
- open: isImportOpen,
10517
- onOpenChange: setIsImportOpen,
10518
- slug,
10519
- schema
10520
10621
  })
10521
10622
  ]
10522
10623
  });
@@ -12604,6 +12705,18 @@ function GlobalEditorPage() {
12604
12705
  //#region src/pages/setup/setup-prompt.tsx
12605
12706
  var GUIDE_URL = "https://www.dyrected.com/guide";
12606
12707
  var DOCS_URL = "https://docs.dyrected.com";
12708
+ var steps = [
12709
+ "Paste the prompt into your AI builder — the same one that owns the website code.",
12710
+ "Review the content list the AI sends back. Correct anything missing or wrong, then say \"approved\".",
12711
+ "Your Dyrected credentials are already in the prompt. Give them to the AI when it asks at Stage 4.",
12712
+ "Test one real edit in Dyrected. If the change appears on the website, invite the client."
12713
+ ];
12714
+ var stepsNoCredentials = [
12715
+ "Paste the prompt into your AI builder — the same one that owns the website code.",
12716
+ "Review the content list the AI sends back. Correct anything missing or wrong, then say \"approved\".",
12717
+ "When the AI reaches Stage 4, it will ask for your Site ID, Site API key, and Base URL.",
12718
+ "Test one real edit in Dyrected. If the change appears on the website, invite the client."
12719
+ ];
12607
12720
  function normalizeTechStack(techStack) {
12608
12721
  if (!techStack) return void 0;
12609
12722
  if (techStack === "next") return "nextjs";
@@ -12619,154 +12732,116 @@ function buildGuideUrl(config) {
12619
12732
  if (config.baseUrl) url.searchParams.set("endpoint", config.baseUrl);
12620
12733
  return url.toString();
12621
12734
  }
12735
+ function buildPrompt(config) {
12736
+ const { siteId, apiKey, baseUrl } = config;
12737
+ if (!(siteId && apiKey && baseUrl)) return GENERATE_CMS_PROMPT;
12738
+ const placeholder = `Ask me for the following in one message:
12739
+
12740
+ - Site ID
12741
+ - Site API key
12742
+ - Base URL
12743
+
12744
+ Wait for my reply.`;
12745
+ const replacement = `Use the following credentials:
12746
+
12747
+ - Site ID: ${siteId}
12748
+ - Site API key: ${apiKey}
12749
+ - Base URL: ${baseUrl}`;
12750
+ return GENERATE_CMS_PROMPT.replace(placeholder, replacement);
12751
+ }
12622
12752
  function SetupPromptUI({ config }) {
12753
+ const [copied, setCopied] = useState(false);
12623
12754
  const guideUrl = buildGuideUrl(config);
12624
- const stack = normalizeTechStack(config.defaultTechStack);
12755
+ const hasCredentials = !!(config.siteId && config.apiKey && config.baseUrl);
12756
+ const guideSteps = hasCredentials ? steps : stepsNoCredentials;
12757
+ const promptText = buildPrompt(config);
12758
+ async function copyPrompt() {
12759
+ await navigator.clipboard.writeText(promptText);
12760
+ setCopied(true);
12761
+ window.setTimeout(() => setCopied(false), 1800);
12762
+ }
12625
12763
  return /* @__PURE__ */ jsxs("div", {
12626
- className: "dy-mx-auto dy-max-w-5xl dy-py-6 lg:dy-py-10",
12627
- children: [/* @__PURE__ */ jsxs("section", {
12628
- className: "dy-relative dy-overflow-hidden dy-rounded-[28px] dy-border dy-border-border dy-bg-card dy-text-card-foreground dy-shadow-2xl",
12629
- children: [
12630
- /* @__PURE__ */ jsx("div", {
12631
- className: "dy-absolute dy-inset-y-0 dy-right-0 dy-w-1/3 dy-bg-primary",
12632
- "aria-hidden": "true"
12633
- }),
12634
- /* @__PURE__ */ jsx("div", {
12635
- className: "dy-absolute dy-inset-y-0 dy-right-[12%] dy-w-40 dy-skew-x-[-12deg] dy-bg-card",
12636
- "aria-hidden": "true"
12637
- }),
12638
- /* @__PURE__ */ jsxs("div", {
12639
- className: "dy-relative dy-grid dy-min-h-[340px] dy-gap-10 dy-p-7 sm:dy-p-10 lg:dy-grid-cols-[1.35fr_0.65fr] lg:dy-p-12",
12640
- children: [/* @__PURE__ */ jsxs("div", {
12641
- className: "dy-flex dy-flex-col dy-justify-between dy-gap-12",
12642
- children: [/* @__PURE__ */ jsxs("div", {
12643
- className: "dy-space-y-6",
12644
- children: [/* @__PURE__ */ jsxs("div", {
12645
- className: "dy-inline-flex dy-items-center dy-gap-2 dy-rounded-full dy-border dy-border-border dy-bg-muted/60 dy-px-3 dy-py-1.5 dy-text-[11px] dy-font-bold dy-uppercase dy-tracking-[0.14em] dy-text-muted-foreground",
12646
- children: [/* @__PURE__ */ jsx(Sparkles, { className: "dy-h-3.5 dy-w-3.5 dy-text-primary" }), "Dyrected setup"]
12647
- }), /* @__PURE__ */ jsxs("div", {
12648
- className: "dy-max-w-2xl dy-space-y-4",
12649
- children: [/* @__PURE__ */ jsx("h1", {
12650
- className: "dy-font-serif dy-text-4xl dy-font-bold dy-leading-[0.98] dy-tracking-tight sm:dy-text-5xl lg:dy-text-6xl",
12651
- children: "Let the guide do the heavy lifting."
12652
- }), /* @__PURE__ */ jsx("p", {
12653
- className: "dy-max-w-xl dy-text-base dy-leading-7 dy-text-muted-foreground sm:dy-text-lg",
12654
- children: "Get a guided path tailored to your project, whether you are building with an AI coding tool or wiring up the SDK yourself."
12655
- })]
12656
- })]
12657
- }), /* @__PURE__ */ jsxs("div", {
12658
- className: "dy-flex dy-flex-col dy-gap-3 sm:dy-flex-row sm:dy-items-center",
12659
- children: [/* @__PURE__ */ jsx(Button, {
12660
- asChild: true,
12661
- size: "lg",
12662
- className: "dy-h-12 dy-bg-primary dy-px-6 dy-text-primary-foreground hover:dy-bg-primary/90",
12663
- children: /* @__PURE__ */ jsxs("a", {
12664
- href: guideUrl,
12665
- target: "_blank",
12666
- rel: "noopener noreferrer",
12667
- children: [
12668
- /* @__PURE__ */ jsx(Compass, { className: "dy-h-4 dy-w-4" }),
12669
- "Open guided setup",
12670
- /* @__PURE__ */ jsx(ArrowUpRight, { className: "dy-h-4 dy-w-4" })
12671
- ]
12672
- })
12673
- }), /* @__PURE__ */ jsx(Button, {
12674
- asChild: true,
12675
- size: "lg",
12676
- variant: "ghost",
12677
- className: "dy-h-12 dy-text-card-foreground hover:dy-bg-muted hover:dy-text-card-foreground",
12678
- children: /* @__PURE__ */ jsxs("a", {
12679
- href: DOCS_URL,
12680
- target: "_blank",
12681
- rel: "noopener noreferrer",
12682
- children: [/* @__PURE__ */ jsx(BookOpen, { className: "dy-h-4 dy-w-4" }), "Browse developer docs"]
12683
- })
12684
- })]
12685
- })]
12686
- }), /* @__PURE__ */ jsx("div", {
12687
- className: "dy-relative dy-flex dy-items-end lg:dy-justify-end",
12688
- children: /* @__PURE__ */ jsxs("div", {
12689
- className: "dy-w-full dy-max-w-sm dy-rounded-2xl dy-border dy-border-border dy-bg-background/90 dy-p-5 dy-text-foreground dy-shadow-lg dy-backdrop-blur-sm",
12690
- children: [/* @__PURE__ */ jsxs("div", {
12691
- className: "dy-mb-5 dy-flex dy-items-center dy-justify-between",
12692
- children: [/* @__PURE__ */ jsx("span", {
12693
- className: "dy-text-xs dy-font-bold dy-uppercase dy-tracking-[0.12em] dy-text-muted-foreground",
12694
- children: "Context included"
12695
- }), /* @__PURE__ */ jsx(Code2, { className: "dy-h-4 dy-w-4 dy-text-primary" })]
12696
- }), /* @__PURE__ */ jsxs("dl", {
12697
- className: "dy-space-y-4 dy-text-sm",
12698
- children: [/* @__PURE__ */ jsxs("div", {
12699
- className: "dy-flex dy-items-center dy-justify-between dy-gap-4",
12700
- children: [/* @__PURE__ */ jsx("dt", {
12701
- className: "dy-text-muted-foreground",
12702
- children: "Tech stack"
12703
- }), /* @__PURE__ */ jsx("dd", {
12704
- className: "dy-font-mono dy-font-semibold dy-text-foreground",
12705
- children: stack ?? "Choose in guide"
12706
- })]
12707
- }), /* @__PURE__ */ jsxs("div", {
12708
- className: "dy-flex dy-items-center dy-justify-between dy-gap-4",
12709
- children: [/* @__PURE__ */ jsx("dt", {
12710
- className: "dy-text-muted-foreground",
12711
- children: "Site"
12712
- }), /* @__PURE__ */ jsx("dd", {
12713
- className: "dy-max-w-[180px] dy-truncate dy-font-mono dy-font-semibold dy-text-foreground",
12714
- children: config.siteId || "Not provided"
12715
- })]
12716
- })]
12717
- })]
12718
- })
12764
+ className: "dy-mx-auto dy-max-w-3xl dy-space-y-10 dy-px-4 dy-py-8",
12765
+ children: [
12766
+ /* @__PURE__ */ jsxs("div", {
12767
+ className: "dy-space-y-2",
12768
+ children: [/* @__PURE__ */ jsx("h1", {
12769
+ className: "dy-text-2xl dy-font-semibold dy-tracking-tight dy-text-foreground",
12770
+ children: "Set up Dyrected"
12771
+ }), /* @__PURE__ */ jsx("p", {
12772
+ className: "dy-text-sm dy-leading-6 dy-text-muted-foreground",
12773
+ children: "Copy the prompt below and paste it into your AI builder. It handles the setup in stages."
12774
+ })]
12775
+ }),
12776
+ /* @__PURE__ */ jsx("ol", {
12777
+ className: "dy-space-y-3",
12778
+ children: guideSteps.map((step, index) => /* @__PURE__ */ jsxs("li", {
12779
+ className: "dy-flex dy-gap-3 dy-text-sm",
12780
+ children: [/* @__PURE__ */ jsx("span", {
12781
+ className: "dy-flex dy-h-6 dy-w-6 dy-shrink-0 dy-items-center dy-justify-center dy-rounded-full dy-bg-muted dy-text-xs dy-font-semibold dy-tabular-nums dy-text-foreground",
12782
+ children: index + 1
12783
+ }), /* @__PURE__ */ jsx("span", {
12784
+ className: "dy-leading-6 dy-text-muted-foreground",
12785
+ children: step
12719
12786
  })]
12720
- })
12721
- ]
12722
- }), /* @__PURE__ */ jsxs("div", {
12723
- className: "dy-grid dy-gap-4 dy-px-1 dy-pt-5 md:dy-grid-cols-2",
12724
- children: [/* @__PURE__ */ jsxs("a", {
12725
- href: guideUrl,
12726
- target: "_blank",
12727
- rel: "noopener noreferrer",
12728
- className: "dy-group dy-flex dy-items-start dy-gap-4 dy-rounded-xl dy-border dy-bg-card dy-p-5 dy-transition-colors hover:dy-border-primary/60 hover:dy-bg-primary/[0.04] focus-visible:dy-outline-none focus-visible:dy-ring-2 focus-visible:dy-ring-ring",
12787
+ }, index))
12788
+ }),
12789
+ /* @__PURE__ */ jsxs("div", {
12790
+ className: "dy-overflow-hidden dy-rounded-xl dy-border dy-border-border dy-bg-card",
12729
12791
  children: [
12730
- /* @__PURE__ */ jsx("div", {
12731
- className: "dy-rounded-lg dy-bg-primary/15 dy-p-2.5 dy-text-foreground",
12732
- children: /* @__PURE__ */ jsx(Sparkles, { className: "dy-h-5 dy-w-5" })
12733
- }),
12734
12792
  /* @__PURE__ */ jsxs("div", {
12735
- className: "dy-min-w-0 dy-flex-1",
12736
- children: [/* @__PURE__ */ jsx("h2", {
12737
- className: "dy-font-semibold dy-text-card-foreground",
12738
- children: "Building with AI?"
12739
- }), /* @__PURE__ */ jsx("p", {
12740
- className: "dy-mt-1 dy-text-sm dy-leading-6 dy-text-muted-foreground",
12741
- children: "The guide gives your coding agent the right context and walks you through each decision."
12793
+ className: "dy-flex dy-items-center dy-justify-between dy-gap-4 dy-border-b dy-border-border dy-px-4 dy-py-3",
12794
+ children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("p", {
12795
+ className: "dy-text-xs dy-font-semibold dy-uppercase dy-tracking-[0.12em] dy-text-muted-foreground",
12796
+ children: "Dyrected setup prompt"
12797
+ }), hasCredentials && /* @__PURE__ */ jsxs("p", {
12798
+ className: "dy-mt-0.5 dy-text-xs dy-text-muted-foreground",
12799
+ children: ["Credentials pre-filled for ", config.siteName || config.siteId]
12800
+ })] }), /* @__PURE__ */ jsxs("button", {
12801
+ type: "button",
12802
+ onClick: copyPrompt,
12803
+ className: "dy-inline-flex dy-items-center dy-gap-1.5 dy-rounded-lg dy-border dy-border-border dy-bg-background dy-px-3 dy-py-1.5 dy-text-xs dy-font-semibold dy-text-foreground dy-transition-colors hover:dy-bg-muted",
12804
+ children: [copied ? /* @__PURE__ */ jsx(Check, { className: "dy-h-3.5 dy-w-3.5 dy-text-primary" }) : /* @__PURE__ */ jsx(Copy, { className: "dy-h-3.5 dy-w-3.5" }), copied ? "Copied" : "Copy prompt"]
12742
12805
  })]
12743
12806
  }),
12744
- /* @__PURE__ */ jsx(ArrowUpRight, { className: "dy-h-4 dy-w-4 dy-text-muted-foreground dy-transition-transform group-hover:dy-translate-x-0.5 group-hover:dy--translate-y-0.5" })
12807
+ /* @__PURE__ */ jsx("pre", {
12808
+ className: "dy-max-h-64 dy-overflow-y-auto dy-p-4 dy-text-[11px] dy-leading-5 dy-text-muted-foreground",
12809
+ children: /* @__PURE__ */ jsx("code", { children: promptText })
12810
+ }),
12811
+ /* @__PURE__ */ jsx("div", {
12812
+ className: "dy-border-t dy-border-border dy-px-4 dy-py-3",
12813
+ children: /* @__PURE__ */ jsxs("p", {
12814
+ className: "dy-text-xs dy-text-muted-foreground",
12815
+ children: ["Paste this into the AI builder or code agent that can edit the website code.", !hasCredentials && " The prompt will ask for your Dyrected details at the right stage."]
12816
+ })
12817
+ })
12745
12818
  ]
12746
- }), /* @__PURE__ */ jsxs("a", {
12747
- href: DOCS_URL,
12748
- target: "_blank",
12749
- rel: "noopener noreferrer",
12750
- className: "dy-group dy-flex dy-items-start dy-gap-4 dy-rounded-xl dy-border dy-bg-card dy-p-5 dy-transition-colors hover:dy-border-foreground/30 hover:dy-bg-muted/40 focus-visible:dy-outline-none focus-visible:dy-ring-2 focus-visible:dy-ring-ring",
12819
+ }),
12820
+ /* @__PURE__ */ jsxs("div", {
12821
+ className: "dy-flex dy-flex-col dy-gap-2 sm:dy-flex-row",
12751
12822
  children: [
12752
- /* @__PURE__ */ jsx("div", {
12753
- className: "dy-rounded-lg dy-bg-muted dy-p-2.5 dy-text-foreground",
12754
- children: /* @__PURE__ */ jsx(BookOpen, { className: "dy-h-5 dy-w-5" })
12823
+ /* @__PURE__ */ jsxs("a", {
12824
+ href: guideUrl,
12825
+ target: "_blank",
12826
+ rel: "noopener noreferrer",
12827
+ className: "dy-inline-flex dy-items-center dy-gap-1.5 dy-text-sm dy-text-muted-foreground dy-underline-offset-4 hover:dy-text-foreground hover:dy-underline",
12828
+ children: ["Full guide", /* @__PURE__ */ jsx(ArrowUpRight, { className: "dy-h-3.5 dy-w-3.5" })]
12755
12829
  }),
12756
- /* @__PURE__ */ jsxs("div", {
12757
- className: "dy-min-w-0 dy-flex-1",
12758
- children: [/* @__PURE__ */ jsx("h2", {
12759
- className: "dy-font-semibold dy-text-card-foreground",
12760
- children: "Need implementation detail?"
12761
- }), /* @__PURE__ */ jsx("p", {
12762
- className: "dy-mt-1 dy-text-sm dy-leading-6 dy-text-muted-foreground",
12763
- children: "Use the docs for SDK APIs, framework integrations, configuration, and production reference."
12764
- })]
12830
+ /* @__PURE__ */ jsx("span", {
12831
+ className: "dy-hidden dy-text-muted-foreground sm:dy-inline",
12832
+ "aria-hidden": "true",
12833
+ children: "·"
12765
12834
  }),
12766
- /* @__PURE__ */ jsx(ArrowUpRight, { className: "dy-h-4 dy-w-4 dy-text-muted-foreground dy-transition-transform group-hover:dy-translate-x-0.5 group-hover:dy--translate-y-0.5" })
12835
+ /* @__PURE__ */ jsxs("a", {
12836
+ href: DOCS_URL,
12837
+ target: "_blank",
12838
+ rel: "noopener noreferrer",
12839
+ className: "dy-inline-flex dy-items-center dy-gap-1.5 dy-text-sm dy-text-muted-foreground dy-underline-offset-4 hover:dy-text-foreground hover:dy-underline",
12840
+ children: ["Developer docs", /* @__PURE__ */ jsx(ArrowUpRight, { className: "dy-h-3.5 dy-w-3.5" })]
12841
+ })
12767
12842
  ]
12768
- })]
12769
- })]
12843
+ })
12844
+ ]
12770
12845
  });
12771
12846
  }
12772
12847
  //#endregion
@@ -13410,8 +13485,7 @@ function buildProviderStartUrl(baseUrl, providerId) {
13410
13485
  }
13411
13486
  function resolveAdminAuthCollection(collections, collectionSlug) {
13412
13487
  if (!collections) return void 0;
13413
- if (collectionSlug) return collections.find((collection) => collection.slug === collectionSlug);
13414
- return collections.find((collection) => collection.slug === "__admins") ?? collections.find((collection) => collection.auth);
13488
+ return collections.find((collection) => collection.slug === "__admins") ?? collections.find((collection) => collection.slug === collectionSlug) ?? collections.find((collection) => collection.auth);
13415
13489
  }
13416
13490
  function readToken(value) {
13417
13491
  if (!value || typeof value !== "object" || !("token" in value)) return null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dyrected/admin",
3
- "version": "2.5.47",
3
+ "version": "2.5.48",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist"
@@ -64,8 +64,9 @@
64
64
  "tailwind-merge": "^3.5.0",
65
65
  "tailwindcss-animate": "^1.0.7",
66
66
  "zod": "^3.25.76",
67
- "@dyrected/core": "^2.5.47",
68
- "@dyrected/sdk": "^2.5.47"
67
+ "@dyrected/core": "^2.5.48",
68
+ "@dyrected/knowledge": "^0.2.5",
69
+ "@dyrected/sdk": "^2.5.48"
69
70
  },
70
71
  "peerDependencies": {
71
72
  "@tanstack/react-query": "^5.0.0",