@ohhwells/bridge 0.1.46 → 0.1.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.
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  // src/OhhwellsBridge.tsx
4
- import React11, { useCallback as useCallback4, useEffect as useEffect8, useLayoutEffect as useLayoutEffect3, useRef as useRef7, useState as useState7 } from "react";
4
+ import React11, { useCallback as useCallback4, useEffect as useEffect9, useLayoutEffect as useLayoutEffect3, useRef as useRef7, useState as useState8 } from "react";
5
5
  import { createRoot } from "react-dom/client";
6
6
  import { flushSync } from "react-dom";
7
7
 
@@ -4843,6 +4843,61 @@ function MediaOverlay({
4843
4843
  ] });
4844
4844
  }
4845
4845
 
4846
+ // src/ui/CarouselOverlay.tsx
4847
+ import { GalleryHorizontal } from "lucide-react";
4848
+ import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
4849
+ var OVERLAY_BUTTON_STYLE2 = {
4850
+ pointerEvents: "auto",
4851
+ fontFamily: "Inter, sans-serif",
4852
+ fontSize: 12,
4853
+ color: "#000"
4854
+ };
4855
+ function CarouselOverlay({
4856
+ hover,
4857
+ onEdit
4858
+ }) {
4859
+ const { rect } = hover;
4860
+ return /* @__PURE__ */ jsx12(
4861
+ "div",
4862
+ {
4863
+ "data-ohw-bridge": "",
4864
+ "data-ohw-carousel-overlay": "",
4865
+ className: "flex cursor-pointer items-center justify-center",
4866
+ style: {
4867
+ position: "fixed",
4868
+ top: rect.top,
4869
+ left: rect.left,
4870
+ width: rect.width,
4871
+ height: rect.height,
4872
+ zIndex: 2147483646,
4873
+ pointerEvents: "auto",
4874
+ boxShadow: "inset 0 0 0 1.5px var(--color-primary)",
4875
+ background: "color-mix(in srgb, var(--color-primary) 20%, transparent)"
4876
+ },
4877
+ onClick: () => onEdit(hover.key),
4878
+ children: /* @__PURE__ */ jsxs6(
4879
+ Button,
4880
+ {
4881
+ "data-ohw-carousel-overlay": "",
4882
+ variant: "outline",
4883
+ size: "sm",
4884
+ className: "cursor-pointer gap-1.5 hover:bg-background",
4885
+ style: OVERLAY_BUTTON_STYLE2,
4886
+ onMouseDown: (e) => e.preventDefault(),
4887
+ onClick: (e) => {
4888
+ e.stopPropagation();
4889
+ onEdit(hover.key);
4890
+ },
4891
+ children: [
4892
+ /* @__PURE__ */ jsx12(GalleryHorizontal, { size: 14 }),
4893
+ "Edit gallery"
4894
+ ]
4895
+ }
4896
+ )
4897
+ }
4898
+ );
4899
+ }
4900
+
4846
4901
  // src/OhhwellsBridge.tsx
4847
4902
  import { createPortal as createPortal2 } from "react-dom";
4848
4903
  import { usePathname as usePathname2, useRouter as useRouter2, useSearchParams } from "next/navigation";
@@ -5129,22 +5184,22 @@ import { useEffect as useEffect6 } from "react";
5129
5184
  import * as React8 from "react";
5130
5185
  import { Dialog as DialogPrimitive } from "radix-ui";
5131
5186
  import { X } from "lucide-react";
5132
- import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
5187
+ import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
5133
5188
  function Dialog2({
5134
5189
  ...props
5135
5190
  }) {
5136
- return /* @__PURE__ */ jsx12(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
5191
+ return /* @__PURE__ */ jsx13(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
5137
5192
  }
5138
5193
  function DialogPortal({
5139
5194
  ...props
5140
5195
  }) {
5141
- return /* @__PURE__ */ jsx12(DialogPrimitive.Portal, { ...props });
5196
+ return /* @__PURE__ */ jsx13(DialogPrimitive.Portal, { ...props });
5142
5197
  }
5143
5198
  function DialogOverlay({
5144
5199
  className,
5145
5200
  ...props
5146
5201
  }) {
5147
- return /* @__PURE__ */ jsx12(
5202
+ return /* @__PURE__ */ jsx13(
5148
5203
  DialogPrimitive.Overlay,
5149
5204
  {
5150
5205
  "data-slot": "dialog-overlay",
@@ -5157,9 +5212,9 @@ function DialogOverlay({
5157
5212
  var DialogContent = React8.forwardRef(
5158
5213
  ({ className, children, showCloseButton = true, container, ...props }, ref) => {
5159
5214
  const positionMode = container ? "absolute" : "fixed";
5160
- return /* @__PURE__ */ jsxs6(DialogPortal, { container: container ?? void 0, children: [
5161
- /* @__PURE__ */ jsx12(DialogOverlay, { className: cn(positionMode, "inset-0") }),
5162
- /* @__PURE__ */ jsxs6(
5215
+ return /* @__PURE__ */ jsxs7(DialogPortal, { container: container ?? void 0, children: [
5216
+ /* @__PURE__ */ jsx13(DialogOverlay, { className: cn(positionMode, "inset-0") }),
5217
+ /* @__PURE__ */ jsxs7(
5163
5218
  DialogPrimitive.Content,
5164
5219
  {
5165
5220
  ref,
@@ -5175,13 +5230,13 @@ var DialogContent = React8.forwardRef(
5175
5230
  ...props,
5176
5231
  children: [
5177
5232
  children,
5178
- showCloseButton ? /* @__PURE__ */ jsx12(
5233
+ showCloseButton ? /* @__PURE__ */ jsx13(
5179
5234
  DialogPrimitive.Close,
5180
5235
  {
5181
5236
  type: "button",
5182
5237
  className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
5183
5238
  "aria-label": "Close",
5184
- children: /* @__PURE__ */ jsx12(X, { size: 16, "aria-hidden": true })
5239
+ children: /* @__PURE__ */ jsx13(X, { size: 16, "aria-hidden": true })
5185
5240
  }
5186
5241
  ) : null
5187
5242
  ]
@@ -5195,13 +5250,13 @@ function DialogHeader({
5195
5250
  className,
5196
5251
  ...props
5197
5252
  }) {
5198
- return /* @__PURE__ */ jsx12("div", { className: cn("flex flex-col gap-1.5", className), ...props });
5253
+ return /* @__PURE__ */ jsx13("div", { className: cn("flex flex-col gap-1.5", className), ...props });
5199
5254
  }
5200
5255
  function DialogFooter({
5201
5256
  className,
5202
5257
  ...props
5203
5258
  }) {
5204
- return /* @__PURE__ */ jsx12(
5259
+ return /* @__PURE__ */ jsx13(
5205
5260
  "div",
5206
5261
  {
5207
5262
  className: cn("flex items-center justify-end gap-2", className),
@@ -5209,7 +5264,7 @@ function DialogFooter({
5209
5264
  }
5210
5265
  );
5211
5266
  }
5212
- var DialogTitle = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx12(
5267
+ var DialogTitle = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx13(
5213
5268
  DialogPrimitive.Title,
5214
5269
  {
5215
5270
  ref,
@@ -5221,7 +5276,7 @@ var DialogTitle = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE
5221
5276
  }
5222
5277
  ));
5223
5278
  DialogTitle.displayName = DialogPrimitive.Title.displayName;
5224
- var DialogDescription = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx12(
5279
+ var DialogDescription = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx13(
5225
5280
  DialogPrimitive.Description,
5226
5281
  {
5227
5282
  ref,
@@ -5237,19 +5292,19 @@ import { Info, X as X3 } from "lucide-react";
5237
5292
 
5238
5293
  // src/ui/link-modal/DestinationBreadcrumb.tsx
5239
5294
  import { ArrowRight, File, GalleryVertical } from "lucide-react";
5240
- import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
5295
+ import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
5241
5296
  function DestinationBreadcrumb({
5242
5297
  pageTitle,
5243
5298
  sectionLabel
5244
5299
  }) {
5245
- return /* @__PURE__ */ jsxs7("div", { className: "flex w-full flex-col gap-2", children: [
5246
- /* @__PURE__ */ jsx13("p", { className: "text-sm font-medium! text-foreground m-0", children: "Destination" }),
5247
- /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-3", children: [
5248
- /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2", children: [
5249
- /* @__PURE__ */ jsx13(File, { size: 16, className: "shrink-0 text-foreground", "aria-hidden": true }),
5250
- /* @__PURE__ */ jsx13("span", { className: "text-sm font-medium leading-none text-foreground!", children: pageTitle })
5300
+ return /* @__PURE__ */ jsxs8("div", { className: "flex w-full flex-col gap-2", children: [
5301
+ /* @__PURE__ */ jsx14("p", { className: "text-sm font-medium! text-foreground m-0", children: "Destination" }),
5302
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-3", children: [
5303
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
5304
+ /* @__PURE__ */ jsx14(File, { size: 16, className: "shrink-0 text-foreground", "aria-hidden": true }),
5305
+ /* @__PURE__ */ jsx14("span", { className: "text-sm font-medium leading-none text-foreground!", children: pageTitle })
5251
5306
  ] }),
5252
- /* @__PURE__ */ jsx13(
5307
+ /* @__PURE__ */ jsx14(
5253
5308
  ArrowRight,
5254
5309
  {
5255
5310
  size: 16,
@@ -5257,8 +5312,8 @@ function DestinationBreadcrumb({
5257
5312
  "aria-hidden": true
5258
5313
  }
5259
5314
  ),
5260
- /* @__PURE__ */ jsxs7("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
5261
- /* @__PURE__ */ jsx13(
5315
+ /* @__PURE__ */ jsxs8("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
5316
+ /* @__PURE__ */ jsx14(
5262
5317
  GalleryVertical,
5263
5318
  {
5264
5319
  size: 16,
@@ -5266,7 +5321,7 @@ function DestinationBreadcrumb({
5266
5321
  "aria-hidden": true
5267
5322
  }
5268
5323
  ),
5269
- /* @__PURE__ */ jsx13("span", { className: "truncate text-sm font-medium leading-none text-foreground", children: sectionLabel })
5324
+ /* @__PURE__ */ jsx14("span", { className: "truncate text-sm font-medium leading-none text-foreground", children: sectionLabel })
5270
5325
  ] })
5271
5326
  ] })
5272
5327
  ] });
@@ -5274,22 +5329,22 @@ function DestinationBreadcrumb({
5274
5329
 
5275
5330
  // src/ui/link-modal/SectionTreeItem.tsx
5276
5331
  import { GalleryVertical as GalleryVertical2 } from "lucide-react";
5277
- import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
5332
+ import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
5278
5333
  function SectionTreeItem({
5279
5334
  section,
5280
5335
  onSelect,
5281
5336
  selected
5282
5337
  }) {
5283
5338
  const interactive = Boolean(onSelect);
5284
- return /* @__PURE__ */ jsxs8("div", { className: "flex h-9 w-full items-end pl-3", children: [
5285
- /* @__PURE__ */ jsx14(
5339
+ return /* @__PURE__ */ jsxs9("div", { className: "flex h-9 w-full items-end pl-3", children: [
5340
+ /* @__PURE__ */ jsx15(
5286
5341
  "div",
5287
5342
  {
5288
5343
  className: "mr-[-1px] h-9 w-2 shrink-0 rounded-bl-sm border-b border-l border-border mb-4",
5289
5344
  "aria-hidden": true
5290
5345
  }
5291
5346
  ),
5292
- /* @__PURE__ */ jsxs8(
5347
+ /* @__PURE__ */ jsxs9(
5293
5348
  "div",
5294
5349
  {
5295
5350
  role: interactive ? "button" : void 0,
@@ -5307,7 +5362,7 @@ function SectionTreeItem({
5307
5362
  interactive && selected && "border-primary"
5308
5363
  ),
5309
5364
  children: [
5310
- /* @__PURE__ */ jsx14(
5365
+ /* @__PURE__ */ jsx15(
5311
5366
  GalleryVertical2,
5312
5367
  {
5313
5368
  size: 16,
@@ -5315,7 +5370,7 @@ function SectionTreeItem({
5315
5370
  "aria-hidden": true
5316
5371
  }
5317
5372
  ),
5318
- /* @__PURE__ */ jsx14("span", { className: "truncate text-sm font-normal leading-5 text-foreground", children: section.label })
5373
+ /* @__PURE__ */ jsx15("span", { className: "truncate text-sm font-normal leading-5 text-foreground", children: section.label })
5319
5374
  ]
5320
5375
  }
5321
5376
  )
@@ -5327,10 +5382,10 @@ import { useEffect as useEffect3, useId as useId2, useRef as useRef4, useState a
5327
5382
 
5328
5383
  // src/ui/input.tsx
5329
5384
  import * as React9 from "react";
5330
- import { jsx as jsx15 } from "react/jsx-runtime";
5385
+ import { jsx as jsx16 } from "react/jsx-runtime";
5331
5386
  var Input = React9.forwardRef(
5332
5387
  ({ className, type, ...props }, ref) => {
5333
- return /* @__PURE__ */ jsx15(
5388
+ return /* @__PURE__ */ jsx16(
5334
5389
  "input",
5335
5390
  {
5336
5391
  type,
@@ -5349,9 +5404,9 @@ Input.displayName = "Input";
5349
5404
 
5350
5405
  // src/ui/label.tsx
5351
5406
  import { Label as LabelPrimitive } from "radix-ui";
5352
- import { jsx as jsx16 } from "react/jsx-runtime";
5407
+ import { jsx as jsx17 } from "react/jsx-runtime";
5353
5408
  function Label({ className, ...props }) {
5354
- return /* @__PURE__ */ jsx16(
5409
+ return /* @__PURE__ */ jsx17(
5355
5410
  LabelPrimitive.Root,
5356
5411
  {
5357
5412
  "data-slot": "label",
@@ -5363,11 +5418,11 @@ function Label({ className, ...props }) {
5363
5418
 
5364
5419
  // src/ui/link-modal/UrlOrPageInput.tsx
5365
5420
  import { ChevronDown, File as File2, X as X2 } from "lucide-react";
5366
- import { jsx as jsx17, jsxs as jsxs9 } from "react/jsx-runtime";
5421
+ import { jsx as jsx18, jsxs as jsxs10 } from "react/jsx-runtime";
5367
5422
  function FieldChevron({
5368
5423
  onClick
5369
5424
  }) {
5370
- return /* @__PURE__ */ jsx17(
5425
+ return /* @__PURE__ */ jsx18(
5371
5426
  "button",
5372
5427
  {
5373
5428
  type: "button",
@@ -5375,7 +5430,7 @@ function FieldChevron({
5375
5430
  onClick,
5376
5431
  "aria-label": "Open page list",
5377
5432
  tabIndex: -1,
5378
- children: /* @__PURE__ */ jsx17(ChevronDown, { size: 16 })
5433
+ children: /* @__PURE__ */ jsx18(ChevronDown, { size: 16 })
5379
5434
  }
5380
5435
  );
5381
5436
  }
@@ -5436,11 +5491,11 @@ function UrlOrPageInput({
5436
5491
  "data-ohw-link-field flex h-[36px] w-full items-center overflow-hidden rounded-md border bg-background pl-3 pr-3 py-2 outline-none transition-[border-color,box-shadow]",
5437
5492
  urlError ? "border-destructive shadow-[0_0_0_1px_var(--ohw-destructive)]" : isFocused ? "border-primary shadow-[0_0_0_1px_var(--ohw-primary)]" : "border-input"
5438
5493
  );
5439
- return /* @__PURE__ */ jsxs9("div", { className: "flex w-full flex-col gap-2 p-0", children: [
5440
- /* @__PURE__ */ jsx17(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
5441
- /* @__PURE__ */ jsxs9("div", { ref: rootRef, className: "relative w-full", children: [
5442
- /* @__PURE__ */ jsxs9("div", { "data-ohw-link-field": true, className: fieldClassName, children: [
5443
- selectedPage ? /* @__PURE__ */ jsx17("div", { className: "flex shrink-0 items-center pr-2", children: /* @__PURE__ */ jsx17(
5494
+ return /* @__PURE__ */ jsxs10("div", { className: "flex w-full flex-col gap-2 p-0", children: [
5495
+ /* @__PURE__ */ jsx18(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
5496
+ /* @__PURE__ */ jsxs10("div", { ref: rootRef, className: "relative w-full", children: [
5497
+ /* @__PURE__ */ jsxs10("div", { "data-ohw-link-field": true, className: fieldClassName, children: [
5498
+ selectedPage ? /* @__PURE__ */ jsx18("div", { className: "flex shrink-0 items-center pr-2", children: /* @__PURE__ */ jsx18(
5444
5499
  File2,
5445
5500
  {
5446
5501
  size: 16,
@@ -5448,7 +5503,7 @@ function UrlOrPageInput({
5448
5503
  "aria-hidden": true
5449
5504
  }
5450
5505
  ) }) : null,
5451
- readOnly ? /* @__PURE__ */ jsx17("span", { className: "min-w-0 flex-1 truncate text-sm leading-5 text-foreground", children: selectedPage?.title ?? value }) : /* @__PURE__ */ jsx17(
5506
+ readOnly ? /* @__PURE__ */ jsx18("span", { className: "min-w-0 flex-1 truncate text-sm leading-5 text-foreground", children: selectedPage?.title ?? value }) : /* @__PURE__ */ jsx18(
5452
5507
  Input,
5453
5508
  {
5454
5509
  ref: inputRef,
@@ -5474,7 +5529,7 @@ function UrlOrPageInput({
5474
5529
  )
5475
5530
  }
5476
5531
  ),
5477
- selectedPage && !readOnly ? /* @__PURE__ */ jsx17(
5532
+ selectedPage && !readOnly ? /* @__PURE__ */ jsx18(
5478
5533
  "button",
5479
5534
  {
5480
5535
  type: "button",
@@ -5482,26 +5537,26 @@ function UrlOrPageInput({
5482
5537
  onMouseDown: clearSelection,
5483
5538
  "aria-label": "Clear selected page",
5484
5539
  tabIndex: -1,
5485
- children: /* @__PURE__ */ jsx17(X2, { size: 16, "aria-hidden": true })
5540
+ children: /* @__PURE__ */ jsx18(X2, { size: 16, "aria-hidden": true })
5486
5541
  }
5487
5542
  ) : null,
5488
- !readOnly ? /* @__PURE__ */ jsx17(FieldChevron, { onClick: toggleDropdown }) : null
5543
+ !readOnly ? /* @__PURE__ */ jsx18(FieldChevron, { onClick: toggleDropdown }) : null
5489
5544
  ] }),
5490
- dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ jsx17(
5545
+ dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ jsx18(
5491
5546
  "div",
5492
5547
  {
5493
5548
  "data-ohw-link-page-dropdown": "",
5494
5549
  className: "absolute left-0 right-0 top-[calc(100%+4px)] z-50 max-h-48 overflow-auto rounded-lg border border-border bg-popover py-1 shadow-lg",
5495
5550
  onMouseDown: (e) => e.preventDefault(),
5496
- children: filteredPages.map((page) => /* @__PURE__ */ jsxs9(
5551
+ children: filteredPages.map((page) => /* @__PURE__ */ jsxs10(
5497
5552
  "button",
5498
5553
  {
5499
5554
  type: "button",
5500
5555
  className: "flex h-9 w-full items-center gap-2 border-0 bg-transparent px-3 text-left text-sm leading-5 text-foreground outline-none hover:bg-muted",
5501
5556
  onClick: () => onPageSelect(page),
5502
5557
  children: [
5503
- /* @__PURE__ */ jsx17(File2, { size: 16, className: "shrink-0", "aria-hidden": true }),
5504
- /* @__PURE__ */ jsx17("span", { className: "truncate", children: page.title })
5558
+ /* @__PURE__ */ jsx18(File2, { size: 16, className: "shrink-0", "aria-hidden": true }),
5559
+ /* @__PURE__ */ jsx18("span", { className: "truncate", children: page.title })
5505
5560
  ]
5506
5561
  },
5507
5562
  page.path
@@ -5509,34 +5564,34 @@ function UrlOrPageInput({
5509
5564
  }
5510
5565
  ) : null
5511
5566
  ] }),
5512
- urlError ? /* @__PURE__ */ jsx17("p", { className: "text-sm font-medium text-destructive", children: urlError }) : null
5567
+ urlError ? /* @__PURE__ */ jsx18("p", { className: "text-sm font-medium text-destructive", children: urlError }) : null
5513
5568
  ] });
5514
5569
  }
5515
5570
 
5516
5571
  // src/ui/link-modal/LinkEditorPanel.tsx
5517
- import { Fragment as Fragment3, jsx as jsx18, jsxs as jsxs10 } from "react/jsx-runtime";
5572
+ import { Fragment as Fragment3, jsx as jsx19, jsxs as jsxs11 } from "react/jsx-runtime";
5518
5573
  function LinkEditorPanel({ state, onClose }) {
5519
5574
  const isCancel = state.secondaryLabel === "Cancel" || state.secondaryLabel === "Back to sections";
5520
- return /* @__PURE__ */ jsxs10(Fragment3, { children: [
5521
- /* @__PURE__ */ jsx18(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx18(
5575
+ return /* @__PURE__ */ jsxs11(Fragment3, { children: [
5576
+ /* @__PURE__ */ jsx19(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx19(
5522
5577
  "button",
5523
5578
  {
5524
5579
  type: "button",
5525
5580
  className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50 h-7",
5526
5581
  "aria-label": "Close",
5527
5582
  onClick: onClose,
5528
- children: /* @__PURE__ */ jsx18(X3, { size: 16, "aria-hidden": true })
5583
+ children: /* @__PURE__ */ jsx19(X3, { size: 16, "aria-hidden": true })
5529
5584
  }
5530
5585
  ) }),
5531
- /* @__PURE__ */ jsx18(DialogHeader, { className: "w-full gap-1.5 p-6 pr-12", children: /* @__PURE__ */ jsx18(DialogTitle, { className: "m-0 w-full break-words", children: state.title }) }),
5532
- /* @__PURE__ */ jsxs10("div", { className: "flex w-full flex-col gap-3 px-6 pb-8 pt-1", children: [
5533
- state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */ jsx18(
5586
+ /* @__PURE__ */ jsx19(DialogHeader, { className: "w-full gap-1.5 p-6 pr-12", children: /* @__PURE__ */ jsx19(DialogTitle, { className: "m-0 w-full break-words", children: state.title }) }),
5587
+ /* @__PURE__ */ jsxs11("div", { className: "flex w-full flex-col gap-3 px-6 pb-8 pt-1", children: [
5588
+ state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */ jsx19(
5534
5589
  DestinationBreadcrumb,
5535
5590
  {
5536
5591
  pageTitle: state.selectedPage.title,
5537
5592
  sectionLabel: state.selectedSection.label
5538
5593
  }
5539
- ) : /* @__PURE__ */ jsx18(
5594
+ ) : /* @__PURE__ */ jsx19(
5540
5595
  UrlOrPageInput,
5541
5596
  {
5542
5597
  value: state.searchValue,
@@ -5549,8 +5604,8 @@ function LinkEditorPanel({ state, onClose }) {
5549
5604
  urlError: state.urlError
5550
5605
  }
5551
5606
  ),
5552
- state.showChooseSection ? /* @__PURE__ */ jsxs10("div", { className: "flex flex-col justify-center gap-2", children: [
5553
- /* @__PURE__ */ jsx18(
5607
+ state.showChooseSection ? /* @__PURE__ */ jsxs11("div", { className: "flex flex-col justify-center gap-2", children: [
5608
+ /* @__PURE__ */ jsx19(
5554
5609
  Button,
5555
5610
  {
5556
5611
  type: "button",
@@ -5561,15 +5616,15 @@ function LinkEditorPanel({ state, onClose }) {
5561
5616
  children: "Choose a section"
5562
5617
  }
5563
5618
  ),
5564
- /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
5565
- /* @__PURE__ */ jsx18(Info, { size: 16, className: "shrink-0", "aria-hidden": true }),
5566
- /* @__PURE__ */ jsx18("span", { children: "Pick a section this link should scroll to." })
5619
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
5620
+ /* @__PURE__ */ jsx19(Info, { size: 16, className: "shrink-0", "aria-hidden": true }),
5621
+ /* @__PURE__ */ jsx19("span", { children: "Pick a section this link should scroll to." })
5567
5622
  ] })
5568
5623
  ] }) : null,
5569
- state.showSectionRow && state.selectedSection ? /* @__PURE__ */ jsx18(SectionTreeItem, { section: state.selectedSection, selected: true }) : null
5624
+ state.showSectionRow && state.selectedSection ? /* @__PURE__ */ jsx19(SectionTreeItem, { section: state.selectedSection, selected: true }) : null
5570
5625
  ] }),
5571
- /* @__PURE__ */ jsxs10(DialogFooter, { className: "w-full px-6 pb-6", children: [
5572
- /* @__PURE__ */ jsx18(
5626
+ /* @__PURE__ */ jsxs11(DialogFooter, { className: "w-full px-6 pb-6", children: [
5627
+ /* @__PURE__ */ jsx19(
5573
5628
  Button,
5574
5629
  {
5575
5630
  type: "button",
@@ -5584,7 +5639,7 @@ function LinkEditorPanel({ state, onClose }) {
5584
5639
  children: state.secondaryLabel
5585
5640
  }
5586
5641
  ),
5587
- /* @__PURE__ */ jsx18(
5642
+ /* @__PURE__ */ jsx19(
5588
5643
  Button,
5589
5644
  {
5590
5645
  type: "button",
@@ -5607,7 +5662,7 @@ import { useCallback, useEffect as useEffect4, useMemo as useMemo2, useRef as us
5607
5662
  import { createPortal } from "react-dom";
5608
5663
  import { ArrowLeft, Check } from "lucide-react";
5609
5664
  import { usePathname, useRouter } from "next/navigation";
5610
- import { jsx as jsx19, jsxs as jsxs11 } from "react/jsx-runtime";
5665
+ import { jsx as jsx20, jsxs as jsxs12 } from "react/jsx-runtime";
5611
5666
  var DIM_OVERLAY = "rgba(0, 0, 0, 0.45)";
5612
5667
  function rectsEqual(a, b) {
5613
5668
  if (a.size !== b.size) return false;
@@ -5836,7 +5891,7 @@ function SectionPickerOverlay({
5836
5891
  const portalRoot = typeof document !== "undefined" ? document.querySelector("[data-ohw-bridge-root]") ?? document.body : null;
5837
5892
  if (!portalRoot) return null;
5838
5893
  return createPortal(
5839
- /* @__PURE__ */ jsxs11(
5894
+ /* @__PURE__ */ jsxs12(
5840
5895
  "div",
5841
5896
  {
5842
5897
  "data-ohw-section-picker": "",
@@ -5846,12 +5901,12 @@ function SectionPickerOverlay({
5846
5901
  role: "dialog",
5847
5902
  "aria-label": "Choose a section",
5848
5903
  children: [
5849
- /* @__PURE__ */ jsx19(
5904
+ /* @__PURE__ */ jsx20(
5850
5905
  "div",
5851
5906
  {
5852
5907
  className: "pointer-events-auto fixed left-5 z-[2]",
5853
5908
  style: { top: chromeClip.top + 20 },
5854
- children: /* @__PURE__ */ jsxs11(
5909
+ children: /* @__PURE__ */ jsxs12(
5855
5910
  Button,
5856
5911
  {
5857
5912
  type: "button",
@@ -5860,14 +5915,14 @@ function SectionPickerOverlay({
5860
5915
  className: "h-8 min-w-0 gap-1 border-border bg-background px-2 py-1.5 shadow-sm hover:bg-muted cursor-pointer",
5861
5916
  onClick: onBack,
5862
5917
  children: [
5863
- /* @__PURE__ */ jsx19(ArrowLeft, { className: "size-4 shrink-0", "aria-hidden": true }),
5918
+ /* @__PURE__ */ jsx20(ArrowLeft, { className: "size-4 shrink-0", "aria-hidden": true }),
5864
5919
  "Back"
5865
5920
  ]
5866
5921
  }
5867
5922
  )
5868
5923
  }
5869
5924
  ),
5870
- /* @__PURE__ */ jsx19(
5925
+ /* @__PURE__ */ jsx20(
5871
5926
  "div",
5872
5927
  {
5873
5928
  className: "pointer-events-none fixed left-1/2 z-[2] rounded-lg px-4 py-3 text-xs leading-4 tracking-[0.18px] text-white shadow-md",
@@ -5880,7 +5935,7 @@ function SectionPickerOverlay({
5880
5935
  children: "Click on section to select"
5881
5936
  }
5882
5937
  ),
5883
- !isOnTargetPage ? /* @__PURE__ */ jsx19(
5938
+ !isOnTargetPage ? /* @__PURE__ */ jsx20(
5884
5939
  "div",
5885
5940
  {
5886
5941
  className: "pointer-events-none fixed left-1/2 z-[1] -translate-x-1/2 rounded-md px-3 py-2 text-sm text-muted-foreground shadow-sm",
@@ -5888,14 +5943,14 @@ function SectionPickerOverlay({
5888
5943
  children: "Loading page preview\u2026"
5889
5944
  }
5890
5945
  ) : null,
5891
- isOnTargetPage && liveSections.length === 0 ? /* @__PURE__ */ jsx19("div", { className: "pointer-events-auto fixed inset-0 z-[1] flex items-center justify-center bg-muted/40", children: /* @__PURE__ */ jsx19("p", { className: "text-sm text-muted-foreground", children: "No sections found on this page." }) }) : null,
5946
+ isOnTargetPage && liveSections.length === 0 ? /* @__PURE__ */ jsx20("div", { className: "pointer-events-auto fixed inset-0 z-[1] flex items-center justify-center bg-muted/40", children: /* @__PURE__ */ jsx20("p", { className: "text-sm text-muted-foreground", children: "No sections found on this page." }) }) : null,
5892
5947
  isOnTargetPage ? liveSections.map((section) => {
5893
5948
  const rect = rects.get(section.id);
5894
5949
  if (!rect || rect.width <= 0 || rect.height <= 0) return null;
5895
5950
  const isSelected = selectedId === section.id;
5896
5951
  const isHovered = hoveredId === section.id;
5897
5952
  const isLit = isSelected || isHovered;
5898
- return /* @__PURE__ */ jsxs11(
5953
+ return /* @__PURE__ */ jsxs12(
5899
5954
  "button",
5900
5955
  {
5901
5956
  type: "button",
@@ -5910,7 +5965,7 @@ function SectionPickerOverlay({
5910
5965
  "aria-label": `Select section ${section.label}`,
5911
5966
  onClick: () => handleSelect(section),
5912
5967
  children: [
5913
- isLit ? /* @__PURE__ */ jsx19(
5968
+ isLit ? /* @__PURE__ */ jsx20(
5914
5969
  "span",
5915
5970
  {
5916
5971
  className: "pointer-events-none absolute",
@@ -5923,13 +5978,13 @@ function SectionPickerOverlay({
5923
5978
  "aria-hidden": true
5924
5979
  }
5925
5980
  ) : null,
5926
- isSelected ? /* @__PURE__ */ jsx19(
5981
+ isSelected ? /* @__PURE__ */ jsx20(
5927
5982
  "span",
5928
5983
  {
5929
5984
  className: "absolute right-3 top-3 flex size-8 items-center justify-center rounded-full text-white",
5930
5985
  style: { backgroundColor: "var(--ohw-primary, #0885fe)" },
5931
5986
  "aria-hidden": true,
5932
- children: /* @__PURE__ */ jsx19(Check, { className: "size-5" })
5987
+ children: /* @__PURE__ */ jsx20(Check, { className: "size-5" })
5933
5988
  }
5934
5989
  ) : null
5935
5990
  ]
@@ -6109,7 +6164,7 @@ function useLinkModalState({
6109
6164
  }
6110
6165
 
6111
6166
  // src/ui/link-modal/LinkPopover.tsx
6112
- import { Fragment as Fragment4, jsx as jsx20, jsxs as jsxs12 } from "react/jsx-runtime";
6167
+ import { Fragment as Fragment4, jsx as jsx21, jsxs as jsxs13 } from "react/jsx-runtime";
6113
6168
  function postToParent(data) {
6114
6169
  window.parent?.postMessage(data, "*");
6115
6170
  }
@@ -6205,15 +6260,15 @@ function LinkPopover({
6205
6260
  );
6206
6261
  };
6207
6262
  }, [open, sectionPickerActive]);
6208
- return /* @__PURE__ */ jsxs12(Fragment4, { children: [
6209
- /* @__PURE__ */ jsx20(
6263
+ return /* @__PURE__ */ jsxs13(Fragment4, { children: [
6264
+ /* @__PURE__ */ jsx21(
6210
6265
  Dialog2,
6211
6266
  {
6212
6267
  open: open && !sectionPickerActive,
6213
6268
  onOpenChange: (next) => {
6214
6269
  if (!next) onClose?.();
6215
6270
  },
6216
- children: /* @__PURE__ */ jsx20(
6271
+ children: /* @__PURE__ */ jsx21(
6217
6272
  DialogContent,
6218
6273
  {
6219
6274
  ref: panelRef,
@@ -6223,12 +6278,12 @@ function LinkPopover({
6223
6278
  "data-ohw-bridge": "",
6224
6279
  showCloseButton: false,
6225
6280
  className: "gap-0 p-0 w-full max-w-[448px] pointer-events-auto z-[2147483646] overflow-visible",
6226
- children: /* @__PURE__ */ jsx20(LinkEditorPanel, { state, onClose })
6281
+ children: /* @__PURE__ */ jsx21(LinkEditorPanel, { state, onClose })
6227
6282
  }
6228
6283
  )
6229
6284
  }
6230
6285
  ),
6231
- sectionPickerActive && state.selectedPage ? /* @__PURE__ */ jsx20(
6286
+ sectionPickerActive && state.selectedPage ? /* @__PURE__ */ jsx21(
6232
6287
  SectionPickerOverlay,
6233
6288
  {
6234
6289
  pagePath: state.selectedPage.path,
@@ -6600,6 +6655,8 @@ function applyNavOrderToContainer(container, order) {
6600
6655
  if (current.length === expected.length && current.every((key, i) => key === expected[i])) {
6601
6656
  return;
6602
6657
  }
6658
+ const lastCurrentLinkEl = current.length > 0 ? findCounterpartByHrefKey(current[current.length - 1], container) : null;
6659
+ const anchor = lastCurrentLinkEl?.parentElement === container ? lastCurrentLinkEl.nextElementSibling : null;
6603
6660
  const seen = /* @__PURE__ */ new Set();
6604
6661
  for (const hrefKey of desired) {
6605
6662
  if (seen.has(hrefKey)) continue;
@@ -6614,7 +6671,9 @@ function applyNavOrderToContainer(container, order) {
6614
6671
  orderedEls.push(el);
6615
6672
  }
6616
6673
  for (const el of orderedEls) {
6617
- if (container.lastElementChild !== el) {
6674
+ if (anchor) {
6675
+ if (el.nextSibling !== anchor) container.insertBefore(el, anchor);
6676
+ } else if (container.lastElementChild !== el) {
6618
6677
  container.appendChild(el);
6619
6678
  }
6620
6679
  }
@@ -6956,6 +7015,11 @@ function reconcileFooterOrderFromContent(content) {
6956
7015
  }
6957
7016
  applyFooterOrder(order);
6958
7017
  }
7018
+ function isRowLayoutColumn(links) {
7019
+ if (links.length < 2) return false;
7020
+ const firstTop = links[0].getBoundingClientRect().top;
7021
+ return links.every((link) => Math.abs(link.getBoundingClientRect().top - firstTop) < 4);
7022
+ }
6959
7023
  function buildLinkDropSlots(column, columnIndex) {
6960
7024
  const links = listFooterLinksInColumn(column);
6961
7025
  const colRect = column.getBoundingClientRect();
@@ -6973,6 +7037,32 @@ function buildLinkDropSlots(column, columnIndex) {
6973
7037
  });
6974
7038
  return slots;
6975
7039
  }
7040
+ if (isRowLayoutColumn(links)) {
7041
+ for (let i = 0; i <= links.length; i++) {
7042
+ let left;
7043
+ if (i === 0) {
7044
+ left = links[0].getBoundingClientRect().left - barThickness / 2;
7045
+ } else if (i === links.length) {
7046
+ const last = links[links.length - 1].getBoundingClientRect();
7047
+ left = last.right - barThickness / 2;
7048
+ } else {
7049
+ const prev = links[i - 1].getBoundingClientRect();
7050
+ const next = links[i].getBoundingClientRect();
7051
+ left = (prev.right + next.left) / 2 - barThickness / 2;
7052
+ }
7053
+ const heightRef = i === 0 ? links[0].getBoundingClientRect() : i === links.length ? links[links.length - 1].getBoundingClientRect() : links[i].getBoundingClientRect();
7054
+ slots.push({
7055
+ insertIndex: i,
7056
+ columnIndex,
7057
+ left,
7058
+ top: heightRef.top,
7059
+ width: barThickness,
7060
+ height: Math.max(heightRef.height, colRect.height * 0.8),
7061
+ direction: "vertical"
7062
+ });
7063
+ }
7064
+ return slots;
7065
+ }
6976
7066
  for (let i = 0; i <= links.length; i++) {
6977
7067
  let top;
6978
7068
  if (i === 0) {
@@ -7056,8 +7146,7 @@ function hitTestLinkDropSlot(clientX, clientY, draggedHrefKey) {
7056
7146
  return true;
7057
7147
  });
7058
7148
  for (const slot of slots) {
7059
- const cy = slot.top + slot.height / 2;
7060
- const dist = Math.abs(clientY - cy) + (inColX ? 0 : 1e3);
7149
+ const dist = slot.direction === "vertical" ? Math.abs(clientX - (slot.left + slot.width / 2)) : Math.abs(clientY - (slot.top + slot.height / 2));
7061
7150
  if (!best || dist < best.dist) best = { slot, dist };
7062
7151
  }
7063
7152
  }
@@ -7101,9 +7190,10 @@ function lockItemDuringDrag() {
7101
7190
  clearTextSelection();
7102
7191
  }
7103
7192
  function unlockItemDragInteraction() {
7193
+ const wasDragging = document.documentElement.hasAttribute("data-ohw-item-dragging");
7104
7194
  document.documentElement.removeAttribute("data-ohw-footer-press-drag");
7105
7195
  document.documentElement.removeAttribute("data-ohw-item-dragging");
7106
- clearTextSelection();
7196
+ if (wasDragging) clearTextSelection();
7107
7197
  }
7108
7198
  var armFooterPressDrag = armItemPressDrag;
7109
7199
  var lockFooterDuringDrag = lockItemDuringDrag;
@@ -7480,7 +7570,6 @@ function useNavItemDrag({
7480
7570
  const hrefKey = anchor?.getAttribute("data-ohw-href-key") ?? null;
7481
7571
  if (!anchor || !isNavbarHrefKey(hrefKey)) return;
7482
7572
  if (isNavbarButton3(anchor) || isDragHandleDisabled2(anchor)) return;
7483
- armItemPressDrag();
7484
7573
  navPointerDragRef.current = {
7485
7574
  el: anchor,
7486
7575
  startX: e.clientX,
@@ -7507,6 +7596,7 @@ function useNavItemDrag({
7507
7596
  if (dx * dx + dy * dy < THRESHOLD * THRESHOLD) return;
7508
7597
  e.preventDefault();
7509
7598
  pending.started = true;
7599
+ armItemPressDrag();
7510
7600
  clearTextSelection();
7511
7601
  try {
7512
7602
  document.body.setPointerCapture(pending.pointerId);
@@ -7534,7 +7624,8 @@ function useNavItemDrag({
7534
7624
  }
7535
7625
  } catch {
7536
7626
  }
7537
- if (!pending?.started) {
7627
+ if (!pending) return;
7628
+ if (!pending.started) {
7538
7629
  unlockItemDragInteraction();
7539
7630
  return;
7540
7631
  }
@@ -7586,7 +7677,6 @@ function useNavItemDrag({
7586
7677
  const hrefKey = selected.getAttribute("data-ohw-href-key");
7587
7678
  if (!hrefKey || !isNavbarHrefKey(hrefKey)) return false;
7588
7679
  if (isNavbarButton3(selected) || isDragHandleDisabled2(selected)) return false;
7589
- armItemPressDrag();
7590
7680
  navPointerDragRef.current = {
7591
7681
  el: selected,
7592
7682
  startX: clientX,
@@ -7612,15 +7702,99 @@ function useNavItemDrag({
7612
7702
  };
7613
7703
  }
7614
7704
 
7705
+ // src/lib/carousel.ts
7706
+ import { useEffect as useEffect8, useState as useState7 } from "react";
7707
+ var CAROUSEL_ATTR = "data-ohw-carousel";
7708
+ var CAROUSEL_VALUE_ATTR = "data-ohw-carousel-value";
7709
+ var CAROUSEL_SLIDE_ATTR = "data-ohw-carousel-slide";
7710
+ var CAROUSEL_EVENT = "ohw:carousel-change";
7711
+ function listCarouselKeys() {
7712
+ const keys = /* @__PURE__ */ new Set();
7713
+ document.querySelectorAll(`[${CAROUSEL_ATTR}]`).forEach((el) => {
7714
+ const key = el.getAttribute("data-ohw-key");
7715
+ if (key) keys.add(key);
7716
+ });
7717
+ return [...keys];
7718
+ }
7719
+ function containersForKey(key) {
7720
+ return Array.from(
7721
+ document.querySelectorAll(`[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`)
7722
+ );
7723
+ }
7724
+ function isCarouselKey(key) {
7725
+ return containersForKey(key).length > 0;
7726
+ }
7727
+ function parseSlides(raw) {
7728
+ if (!raw) return [];
7729
+ try {
7730
+ const parsed = JSON.parse(raw);
7731
+ if (!Array.isArray(parsed)) return [];
7732
+ return parsed.filter((s) => Boolean(s) && typeof s === "object").map((s) => ({ src: String(s.src ?? ""), alt: String(s.alt ?? "") }));
7733
+ } catch {
7734
+ return [];
7735
+ }
7736
+ }
7737
+ function readCarouselValue(key) {
7738
+ const container = containersForKey(key)[0];
7739
+ if (!container) return [];
7740
+ const fromAttr = parseSlides(container.getAttribute(CAROUSEL_VALUE_ATTR));
7741
+ if (fromAttr.length > 0) return fromAttr;
7742
+ return Array.from(container.querySelectorAll(`[${CAROUSEL_SLIDE_ATTR}]`)).filter((slide) => slide.closest(`[${CAROUSEL_ATTR}]`) === container).sort((a, b) => slideIndex(a) - slideIndex(b)).map((slide) => {
7743
+ const img = slide instanceof HTMLImageElement ? slide : slide.querySelector("img");
7744
+ return { src: img?.src ?? "", alt: img?.alt ?? "" };
7745
+ });
7746
+ }
7747
+ function slideIndex(el) {
7748
+ const raw = el.getAttribute(CAROUSEL_SLIDE_ATTR);
7749
+ const n = raw ? parseInt(raw, 10) : NaN;
7750
+ return Number.isFinite(n) ? n : 0;
7751
+ }
7752
+ function applyCarouselValue(key, slides) {
7753
+ const value = JSON.stringify(slides);
7754
+ for (const container of containersForKey(key)) {
7755
+ if (container.getAttribute(CAROUSEL_VALUE_ATTR) === value) continue;
7756
+ container.setAttribute(CAROUSEL_VALUE_ATTR, value);
7757
+ container.dispatchEvent(
7758
+ new CustomEvent(CAROUSEL_EVENT, { detail: { images: slides } })
7759
+ );
7760
+ }
7761
+ }
7762
+ function applyCarouselNode(key, val) {
7763
+ if (!isCarouselKey(key)) return false;
7764
+ applyCarouselValue(key, parseSlides(val));
7765
+ return true;
7766
+ }
7767
+ function useOhwCarousel(key, initial) {
7768
+ const [images, setImages] = useState7(initial);
7769
+ useEffect8(() => {
7770
+ const el = document.querySelector(
7771
+ `[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`
7772
+ );
7773
+ if (!el) return;
7774
+ const onChange = (e) => {
7775
+ const detail = e.detail;
7776
+ if (Array.isArray(detail?.images)) setImages(detail.images);
7777
+ };
7778
+ el.addEventListener(CAROUSEL_EVENT, onChange);
7779
+ return () => el.removeEventListener(CAROUSEL_EVENT, onChange);
7780
+ }, [key]);
7781
+ const bind = {
7782
+ [CAROUSEL_ATTR]: "",
7783
+ "data-ohw-key": key,
7784
+ [CAROUSEL_VALUE_ATTR]: JSON.stringify(images)
7785
+ };
7786
+ return { images, setImages, bind };
7787
+ }
7788
+
7615
7789
  // src/ui/navbar-container-chrome.tsx
7616
7790
  import { Plus as Plus2 } from "lucide-react";
7617
- import { jsx as jsx21 } from "react/jsx-runtime";
7791
+ import { jsx as jsx22 } from "react/jsx-runtime";
7618
7792
  function NavbarContainerChrome({
7619
7793
  rect,
7620
7794
  onAdd
7621
7795
  }) {
7622
7796
  const chromeGap = 6;
7623
- return /* @__PURE__ */ jsx21(
7797
+ return /* @__PURE__ */ jsx22(
7624
7798
  "div",
7625
7799
  {
7626
7800
  "data-ohw-navbar-container-chrome": "",
@@ -7632,7 +7806,7 @@ function NavbarContainerChrome({
7632
7806
  width: rect.width + chromeGap * 2,
7633
7807
  height: rect.height + chromeGap * 2
7634
7808
  },
7635
- children: /* @__PURE__ */ jsx21(
7809
+ children: /* @__PURE__ */ jsx22(
7636
7810
  "button",
7637
7811
  {
7638
7812
  type: "button",
@@ -7649,7 +7823,7 @@ function NavbarContainerChrome({
7649
7823
  e.stopPropagation();
7650
7824
  onAdd();
7651
7825
  },
7652
- children: /* @__PURE__ */ jsx21(Plus2, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
7826
+ children: /* @__PURE__ */ jsx22(Plus2, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
7653
7827
  }
7654
7828
  )
7655
7829
  }
@@ -7658,7 +7832,7 @@ function NavbarContainerChrome({
7658
7832
 
7659
7833
  // src/ui/drop-indicator.tsx
7660
7834
  import * as React10 from "react";
7661
- import { jsx as jsx22 } from "react/jsx-runtime";
7835
+ import { jsx as jsx23 } from "react/jsx-runtime";
7662
7836
  var dropIndicatorVariants = cva(
7663
7837
  "ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
7664
7838
  {
@@ -7682,7 +7856,7 @@ var dropIndicatorVariants = cva(
7682
7856
  );
7683
7857
  var DropIndicator = React10.forwardRef(
7684
7858
  ({ className, direction, state, ...props }, ref) => {
7685
- return /* @__PURE__ */ jsx22(
7859
+ return /* @__PURE__ */ jsx23(
7686
7860
  "div",
7687
7861
  {
7688
7862
  ref,
@@ -7699,7 +7873,7 @@ var DropIndicator = React10.forwardRef(
7699
7873
  DropIndicator.displayName = "DropIndicator";
7700
7874
 
7701
7875
  // src/ui/badge.tsx
7702
- import { jsx as jsx23 } from "react/jsx-runtime";
7876
+ import { jsx as jsx24 } from "react/jsx-runtime";
7703
7877
  var badgeVariants = cva(
7704
7878
  "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
7705
7879
  {
@@ -7717,12 +7891,12 @@ var badgeVariants = cva(
7717
7891
  }
7718
7892
  );
7719
7893
  function Badge({ className, variant, ...props }) {
7720
- return /* @__PURE__ */ jsx23("div", { className: cn(badgeVariants({ variant }), className), ...props });
7894
+ return /* @__PURE__ */ jsx24("div", { className: cn(badgeVariants({ variant }), className), ...props });
7721
7895
  }
7722
7896
 
7723
7897
  // src/OhhwellsBridge.tsx
7724
7898
  import { Link as Link2 } from "lucide-react";
7725
- import { Fragment as Fragment5, jsx as jsx24, jsxs as jsxs13 } from "react/jsx-runtime";
7899
+ import { Fragment as Fragment5, jsx as jsx25, jsxs as jsxs14 } from "react/jsx-runtime";
7726
7900
  var PRIMARY2 = "#0885FE";
7727
7901
  var IMAGE_FADE_MS = 300;
7728
7902
  function runOpacityFade(el, onDone) {
@@ -7901,7 +8075,7 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
7901
8075
  const root = createRoot(container);
7902
8076
  flushSync(() => {
7903
8077
  root.render(
7904
- /* @__PURE__ */ jsx24(
8078
+ /* @__PURE__ */ jsx25(
7905
8079
  SchedulingWidget,
7906
8080
  {
7907
8081
  notifyOnConnect,
@@ -8019,6 +8193,9 @@ function collectEditableNodes(extraContent) {
8019
8193
  nodes.push({ key: `${key}${VIDEO_AUTOPLAY_SUFFIX}`, type: "video-setting", text: String(video.autoplay) });
8020
8194
  nodes.push({ key: `${key}${VIDEO_MUTED_SUFFIX}`, type: "video-setting", text: String(video.muted) });
8021
8195
  });
8196
+ for (const key of listCarouselKeys()) {
8197
+ nodes.push({ key, type: "carousel", text: JSON.stringify(readCarouselValue(key)) });
8198
+ }
8022
8199
  const seen = /* @__PURE__ */ new Set();
8023
8200
  return nodes.filter((node) => {
8024
8201
  if (!node.key) return true;
@@ -8431,9 +8608,16 @@ function sanitizeHtml(html) {
8431
8608
  if (!SAFE_TAGS.has(el.tagName)) {
8432
8609
  parent.replaceChild(document.createTextNode(el.textContent ?? ""), el);
8433
8610
  } else {
8434
- const textAlign = el.style?.textAlign || el.getAttribute("align") || "";
8611
+ const htmlEl = el;
8612
+ const textAlign = htmlEl.style?.textAlign || el.getAttribute("align") || "";
8613
+ const fontWeight = htmlEl.style?.fontWeight || "";
8614
+ const fontStyle = htmlEl.style?.fontStyle || "";
8615
+ const textDecorationLine = htmlEl.style?.textDecorationLine || htmlEl.style?.textDecoration || "";
8435
8616
  for (const attr of Array.from(el.attributes)) el.removeAttribute(attr.name);
8436
- if (textAlign) el.style.textAlign = textAlign;
8617
+ if (textAlign) htmlEl.style.textAlign = textAlign;
8618
+ if (fontWeight) htmlEl.style.fontWeight = fontWeight;
8619
+ if (fontStyle) htmlEl.style.fontStyle = fontStyle;
8620
+ if (textDecorationLine) htmlEl.style.textDecorationLine = textDecorationLine;
8437
8621
  walk(el);
8438
8622
  }
8439
8623
  }
@@ -8480,7 +8664,7 @@ function EditGlowChrome({
8480
8664
  hideHandle = false
8481
8665
  }) {
8482
8666
  const GAP = SELECTION_CHROME_GAP2;
8483
- return /* @__PURE__ */ jsxs13(
8667
+ return /* @__PURE__ */ jsxs14(
8484
8668
  "div",
8485
8669
  {
8486
8670
  ref: elRef,
@@ -8495,7 +8679,7 @@ function EditGlowChrome({
8495
8679
  zIndex: 2147483646
8496
8680
  },
8497
8681
  children: [
8498
- /* @__PURE__ */ jsx24(
8682
+ /* @__PURE__ */ jsx25(
8499
8683
  "div",
8500
8684
  {
8501
8685
  style: {
@@ -8508,7 +8692,7 @@ function EditGlowChrome({
8508
8692
  }
8509
8693
  }
8510
8694
  ),
8511
- reorderHrefKey && !hideHandle && /* @__PURE__ */ jsx24(
8695
+ reorderHrefKey && !hideHandle && /* @__PURE__ */ jsx25(
8512
8696
  "div",
8513
8697
  {
8514
8698
  "data-ohw-drag-handle-container": "",
@@ -8520,7 +8704,7 @@ function EditGlowChrome({
8520
8704
  transform: "translate(calc(-100% - 7px), -50%)",
8521
8705
  pointerEvents: dragDisabled ? "none" : "auto"
8522
8706
  },
8523
- children: /* @__PURE__ */ jsx24(
8707
+ children: /* @__PURE__ */ jsx25(
8524
8708
  DragHandle,
8525
8709
  {
8526
8710
  "aria-label": `Reorder ${reorderHrefKey}`,
@@ -8621,6 +8805,79 @@ function resolveItemInteractionState(rect, parentScroll) {
8621
8805
  const { transform } = calcToolbarPos(rect, parentScroll, 120);
8622
8806
  return transform.includes("translateY(-100%)") ? "active-top" : "active-bottom";
8623
8807
  }
8808
+ function resolveSelectionStartElement(sel) {
8809
+ if (!sel || sel.rangeCount === 0) return null;
8810
+ const range = sel.getRangeAt(0);
8811
+ let startNode = range.startContainer;
8812
+ if (startNode.nodeType === Node.ELEMENT_NODE) {
8813
+ const el = startNode;
8814
+ startNode = el.childNodes[range.startOffset] ?? el.childNodes[range.startOffset - 1] ?? el;
8815
+ }
8816
+ return startNode.nodeType === Node.TEXT_NODE ? startNode.parentElement : startNode;
8817
+ }
8818
+ function detectActiveFormats(startEl, activeRoot) {
8819
+ const formats = /* @__PURE__ */ new Set();
8820
+ const cs = getComputedStyle(startEl);
8821
+ const weight = parseInt(cs.fontWeight, 10);
8822
+ let hasBold = cs.fontWeight === "bold" || !Number.isNaN(weight) && weight >= 600;
8823
+ let hasItalic = cs.fontStyle === "italic" || cs.fontStyle === "oblique";
8824
+ let hasUnderline = false;
8825
+ let hasStrike = false;
8826
+ let hasUl = false;
8827
+ let hasOl = false;
8828
+ for (let el = startEl; el; el = el.parentElement) {
8829
+ if (el.tagName === "B" || el.tagName === "STRONG") hasBold = true;
8830
+ if (el.tagName === "I" || el.tagName === "EM") hasItalic = true;
8831
+ const decoration = getComputedStyle(el).textDecorationLine;
8832
+ if (decoration.includes("underline") || el.tagName === "U" || el.tagName === "INS") hasUnderline = true;
8833
+ if (decoration.includes("line-through") || el.tagName === "S" || el.tagName === "STRIKE" || el.tagName === "DEL") hasStrike = true;
8834
+ if (el.tagName === "UL") hasUl = true;
8835
+ if (el.tagName === "OL") hasOl = true;
8836
+ if (el === activeRoot) break;
8837
+ }
8838
+ if (hasBold) formats.add("bold");
8839
+ if (hasItalic) formats.add("italic");
8840
+ if (hasUnderline) formats.add("underline");
8841
+ if (hasStrike) formats.add("strikeThrough");
8842
+ if (hasUl) formats.add("insertUnorderedList");
8843
+ if (hasOl) formats.add("insertOrderedList");
8844
+ const block = startEl.closest("div, p, h1, h2, h3, h4, h5, h6, li, td, th") ?? startEl;
8845
+ const align = getComputedStyle(block).textAlign;
8846
+ if (align === "center") formats.add("justifyCenter");
8847
+ else if (align === "right" || align === "end") formats.add("justifyRight");
8848
+ else formats.add("justifyLeft");
8849
+ return formats;
8850
+ }
8851
+ function setsEqual(a, b) {
8852
+ if (a.size !== b.size) return false;
8853
+ for (const item of a) {
8854
+ if (!b.has(item)) return false;
8855
+ }
8856
+ return true;
8857
+ }
8858
+ function textOffsetInRoot(root, node, offset) {
8859
+ const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
8860
+ let total = 0;
8861
+ let current;
8862
+ while (current = walker.nextNode()) {
8863
+ if (current === node) return total + offset;
8864
+ total += (current.textContent ?? "").length;
8865
+ }
8866
+ return total;
8867
+ }
8868
+ function pointAtTextOffset(root, targetOffset) {
8869
+ const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
8870
+ let total = 0;
8871
+ let current;
8872
+ let last = null;
8873
+ while (current = walker.nextNode()) {
8874
+ const len = (current.textContent ?? "").length;
8875
+ if (total + len >= targetOffset) return { node: current, offset: targetOffset - total };
8876
+ total += len;
8877
+ last = current;
8878
+ }
8879
+ return last ? { node: last, offset: (last.textContent ?? "").length } : null;
8880
+ }
8624
8881
  function FloatingToolbar({
8625
8882
  rect,
8626
8883
  parentScroll,
@@ -8657,7 +8914,7 @@ function FloatingToolbar({
8657
8914
  return () => ro.disconnect();
8658
8915
  }, [showEditLink, activeCommands]);
8659
8916
  const { top, left, transform } = calcToolbarPos(rect, parentScroll, measuredW);
8660
- return /* @__PURE__ */ jsx24(
8917
+ return /* @__PURE__ */ jsx25(
8661
8918
  "div",
8662
8919
  {
8663
8920
  ref: setRefs,
@@ -8669,12 +8926,12 @@ function FloatingToolbar({
8669
8926
  zIndex: 2147483647,
8670
8927
  pointerEvents: "auto"
8671
8928
  },
8672
- children: /* @__PURE__ */ jsxs13(CustomToolbar, { children: [
8673
- TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs13(React11.Fragment, { children: [
8674
- gi > 0 && /* @__PURE__ */ jsx24(CustomToolbarDivider, {}),
8929
+ children: /* @__PURE__ */ jsxs14(CustomToolbar, { children: [
8930
+ TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ jsxs14(React11.Fragment, { children: [
8931
+ gi > 0 && /* @__PURE__ */ jsx25(CustomToolbarDivider, {}),
8675
8932
  btns.map((btn) => {
8676
8933
  const isActive = activeCommands.has(btn.cmd);
8677
- return /* @__PURE__ */ jsx24(
8934
+ return /* @__PURE__ */ jsx25(
8678
8935
  CustomToolbarButton,
8679
8936
  {
8680
8937
  title: btn.title,
@@ -8683,7 +8940,7 @@ function FloatingToolbar({
8683
8940
  e.preventDefault();
8684
8941
  onCommand(btn.cmd);
8685
8942
  },
8686
- children: /* @__PURE__ */ jsx24(
8943
+ children: /* @__PURE__ */ jsx25(
8687
8944
  "svg",
8688
8945
  {
8689
8946
  width: "16",
@@ -8704,7 +8961,7 @@ function FloatingToolbar({
8704
8961
  );
8705
8962
  })
8706
8963
  ] }, gi)),
8707
- showEditLink ? /* @__PURE__ */ jsx24(
8964
+ showEditLink ? /* @__PURE__ */ jsx25(
8708
8965
  CustomToolbarButton,
8709
8966
  {
8710
8967
  type: "button",
@@ -8718,7 +8975,7 @@ function FloatingToolbar({
8718
8975
  e.preventDefault();
8719
8976
  e.stopPropagation();
8720
8977
  },
8721
- children: /* @__PURE__ */ jsx24(Link2, { className: "size-4 shrink-0", "aria-hidden": true })
8978
+ children: /* @__PURE__ */ jsx25(Link2, { className: "size-4 shrink-0", "aria-hidden": true })
8722
8979
  }
8723
8980
  ) : null
8724
8981
  ] })
@@ -8735,7 +8992,7 @@ function StateToggle({
8735
8992
  states,
8736
8993
  onStateChange
8737
8994
  }) {
8738
- return /* @__PURE__ */ jsx24(
8995
+ return /* @__PURE__ */ jsx25(
8739
8996
  ToggleGroup,
8740
8997
  {
8741
8998
  "data-ohw-state-toggle": "",
@@ -8749,7 +9006,7 @@ function StateToggle({
8749
9006
  left: rect.right - 8,
8750
9007
  transform: "translateX(-100%)"
8751
9008
  },
8752
- children: states.map((state) => /* @__PURE__ */ jsx24(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
9009
+ children: states.map((state) => /* @__PURE__ */ jsx25(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
8753
9010
  }
8754
9011
  );
8755
9012
  }
@@ -8776,8 +9033,8 @@ function OhhwellsBridge() {
8776
9033
  const router = useRouter2();
8777
9034
  const searchParams = useSearchParams();
8778
9035
  const isEditMode = isEditSessionActive();
8779
- const [bridgeRoot, setBridgeRoot] = useState7(null);
8780
- useEffect8(() => {
9036
+ const [bridgeRoot, setBridgeRoot] = useState8(null);
9037
+ useEffect9(() => {
8781
9038
  const figtreeFontId = "ohw-figtree-font";
8782
9039
  if (!document.getElementById(figtreeFontId)) {
8783
9040
  const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
@@ -8810,9 +9067,10 @@ function OhhwellsBridge() {
8810
9067
  window.parent.postMessage(data, "*");
8811
9068
  }
8812
9069
  }, []);
8813
- const [fetchState, setFetchState] = useState7("idle");
9070
+ const [fetchState, setFetchState] = useState8("idle");
8814
9071
  const autoSaveTimers = useRef7(/* @__PURE__ */ new Map());
8815
9072
  const activeElRef = useRef7(null);
9073
+ const pointerHeldRef = useRef7(false);
8816
9074
  const selectedElRef = useRef7(null);
8817
9075
  const selectedHrefKeyRef = useRef7(null);
8818
9076
  const selectedFooterColAttrRef = useRef7(null);
@@ -8820,7 +9078,7 @@ function OhhwellsBridge() {
8820
9078
  const activeStateElRef = useRef7(null);
8821
9079
  const parentScrollRef = useRef7(null);
8822
9080
  const visibleViewportRef = useRef7(null);
8823
- const [dialogPortalContainer, setDialogPortalContainer] = useState7(null);
9081
+ const [dialogPortalContainer, setDialogPortalContainer] = useState8(null);
8824
9082
  const attachVisibleViewport = useCallback4((node) => {
8825
9083
  visibleViewportRef.current = node;
8826
9084
  setDialogPortalContainer(node);
@@ -8831,8 +9089,9 @@ function OhhwellsBridge() {
8831
9089
  const hoveredImageRef = useRef7(null);
8832
9090
  const hoveredImageHasTextOverlapRef = useRef7(false);
8833
9091
  const dragOverElRef = useRef7(null);
8834
- const [mediaHover, setMediaHover] = useState7(null);
8835
- const [uploadingRects, setUploadingRects] = useState7({});
9092
+ const [mediaHover, setMediaHover] = useState8(null);
9093
+ const [carouselHover, setCarouselHover] = useState8(null);
9094
+ const [uploadingRects, setUploadingRects] = useState8({});
8836
9095
  const hoveredGapRef = useRef7(null);
8837
9096
  const imageUnhoverTimerRef = useRef7(null);
8838
9097
  const imageShowTimerRef = useRef7(null);
@@ -8857,40 +9116,40 @@ function OhhwellsBridge() {
8857
9116
  postToParentRef.current = postToParent2;
8858
9117
  const sectionsLoadedRef = useRef7(false);
8859
9118
  const pendingScheduleConfigRequests = useRef7([]);
8860
- const [toolbarRect, setToolbarRect] = useState7(null);
8861
- const [toolbarVariant, setToolbarVariant] = useState7("none");
9119
+ const [toolbarRect, setToolbarRect] = useState8(null);
9120
+ const [toolbarVariant, setToolbarVariant] = useState8("none");
8862
9121
  const toolbarVariantRef = useRef7("none");
8863
9122
  toolbarVariantRef.current = toolbarVariant;
8864
- const [selectedIsCta, setSelectedIsCta] = useState7(false);
8865
- const [reorderHrefKey, setReorderHrefKey] = useState7(null);
8866
- const [reorderDragDisabled, setReorderDragDisabled] = useState7(false);
8867
- const [toggleState, setToggleState] = useState7(null);
8868
- const [maxBadge, setMaxBadge] = useState7(null);
8869
- const [activeCommands, setActiveCommands] = useState7(/* @__PURE__ */ new Set());
8870
- const [sectionGap, setSectionGap] = useState7(null);
8871
- const [toolbarShowEditLink, setToolbarShowEditLink] = useState7(false);
9123
+ const [selectedIsCta, setSelectedIsCta] = useState8(false);
9124
+ const [reorderHrefKey, setReorderHrefKey] = useState8(null);
9125
+ const [reorderDragDisabled, setReorderDragDisabled] = useState8(false);
9126
+ const [toggleState, setToggleState] = useState8(null);
9127
+ const [maxBadge, setMaxBadge] = useState8(null);
9128
+ const [activeCommands, setActiveCommands] = useState8(/* @__PURE__ */ new Set());
9129
+ const [sectionGap, setSectionGap] = useState8(null);
9130
+ const [toolbarShowEditLink, setToolbarShowEditLink] = useState8(false);
8872
9131
  const hoveredNavContainerRef = useRef7(null);
8873
- const [hoveredNavContainerRect, setHoveredNavContainerRect] = useState7(null);
9132
+ const [hoveredNavContainerRect, setHoveredNavContainerRect] = useState8(null);
8874
9133
  const hoveredItemElRef = useRef7(null);
8875
- const [hoveredItemRect, setHoveredItemRect] = useState7(null);
9134
+ const [hoveredItemRect, setHoveredItemRect] = useState8(null);
8876
9135
  const siblingHintElRef = useRef7(null);
8877
- const [siblingHintRect, setSiblingHintRect] = useState7(null);
8878
- const [siblingHintRects, setSiblingHintRects] = useState7([]);
8879
- const [isItemDragging, setIsItemDragging] = useState7(false);
8880
- const [isFooterFrameSelection, setIsFooterFrameSelection] = useState7(false);
9136
+ const [siblingHintRect, setSiblingHintRect] = useState8(null);
9137
+ const [siblingHintRects, setSiblingHintRects] = useState8([]);
9138
+ const [isItemDragging, setIsItemDragging] = useState8(false);
9139
+ const [isFooterFrameSelection, setIsFooterFrameSelection] = useState8(false);
8881
9140
  const footerDragRef = useRef7(null);
8882
- const [footerDropSlots, setFooterDropSlots] = useState7([]);
8883
- const [activeFooterDropIndex, setActiveFooterDropIndex] = useState7(null);
8884
- const [draggedItemRect, setDraggedItemRect] = useState7(null);
9141
+ const [footerDropSlots, setFooterDropSlots] = useState8([]);
9142
+ const [activeFooterDropIndex, setActiveFooterDropIndex] = useState8(null);
9143
+ const [draggedItemRect, setDraggedItemRect] = useState8(null);
8885
9144
  const footerPointerDragRef = useRef7(null);
8886
9145
  const suppressNextClickRef = useRef7(false);
8887
9146
  const suppressClickUntilRef = useRef7(0);
8888
- const [linkPopover, setLinkPopover] = useState7(null);
9147
+ const [linkPopover, setLinkPopover] = useState8(null);
8889
9148
  const linkPopoverSessionRef = useRef7(null);
8890
9149
  const addNavAfterAnchorRef = useRef7(null);
8891
9150
  const editContentRef = useRef7({});
8892
- const [sitePages, setSitePages] = useState7([]);
8893
- const [sectionsByPath, setSectionsByPath] = useState7({});
9151
+ const [sitePages, setSitePages] = useState8([]);
9152
+ const [sectionsByPath, setSectionsByPath] = useState8({});
8894
9153
  const sectionsPrefetchGenRef = useRef7(0);
8895
9154
  const setLinkPopoverRef = useRef7(setLinkPopover);
8896
9155
  const linkPopoverPanelRef = useRef7(null);
@@ -8955,7 +9214,7 @@ function OhhwellsBridge() {
8955
9214
  }, [isEditMode, pathname]);
8956
9215
  const runSectionsPrefetchRef = useRef7(runSectionsPrefetch);
8957
9216
  runSectionsPrefetchRef.current = runSectionsPrefetch;
8958
- useEffect8(() => {
9217
+ useEffect9(() => {
8959
9218
  if (!linkPopover) {
8960
9219
  document.documentElement.removeAttribute("data-ohw-link-popover-open");
8961
9220
  return;
@@ -9005,7 +9264,7 @@ function OhhwellsBridge() {
9005
9264
  document.removeEventListener("touchmove", preventBackgroundScroll, scrollOpts);
9006
9265
  };
9007
9266
  }, [linkPopover, postToParent2]);
9008
- useEffect8(() => {
9267
+ useEffect9(() => {
9009
9268
  if (!isEditMode) return;
9010
9269
  const useFixtures = shouldUseDevFixtures();
9011
9270
  if (useFixtures) {
@@ -9029,14 +9288,14 @@ function OhhwellsBridge() {
9029
9288
  if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
9030
9289
  return () => window.removeEventListener("message", onSitePages);
9031
9290
  }, [isEditMode, postToParent2]);
9032
- useEffect8(() => {
9291
+ useEffect9(() => {
9033
9292
  if (!isEditMode || shouldUseDevFixtures()) return;
9034
9293
  void loadAllSectionsManifest().then((manifest) => {
9035
9294
  if (Object.keys(manifest).length === 0) return;
9036
9295
  setSectionsByPath((prev) => ({ ...manifest, ...prev }));
9037
9296
  });
9038
9297
  }, [isEditMode]);
9039
- useEffect8(() => {
9298
+ useEffect9(() => {
9040
9299
  const update = () => {
9041
9300
  const el = activeElRef.current ?? selectedElRef.current;
9042
9301
  if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
@@ -9499,7 +9758,6 @@ function OhhwellsBridge() {
9499
9758
  if (e.button !== 0) return;
9500
9759
  const selected = selectedElRef.current;
9501
9760
  if (!selected) return;
9502
- armFooterPressDrag();
9503
9761
  const hrefKey = selected.getAttribute("data-ohw-href-key");
9504
9762
  if (hrefKey && isFooterHrefKey(hrefKey)) {
9505
9763
  footerPointerDragRef.current = {
@@ -9611,6 +9869,8 @@ function OhhwellsBridge() {
9611
9869
  setSiblingHintRect(null);
9612
9870
  setSiblingHintRects([]);
9613
9871
  setIsItemDragging(false);
9872
+ const preActivationSelection = window.getSelection();
9873
+ const preservedRange = preActivationSelection && preActivationSelection.rangeCount > 0 && !preActivationSelection.isCollapsed && el.contains(preActivationSelection.getRangeAt(0).commonAncestorContainer) ? preActivationSelection.getRangeAt(0).cloneRange() : null;
9614
9874
  el.setAttribute("contenteditable", "true");
9615
9875
  el.setAttribute("data-ohw-editing", "");
9616
9876
  el.removeAttribute("data-ohw-hovered");
@@ -9618,7 +9878,11 @@ function OhhwellsBridge() {
9618
9878
  activeElRef.current = el;
9619
9879
  originalContentRef.current = el.innerHTML;
9620
9880
  el.focus({ preventScroll: true });
9621
- if (options?.caretX !== void 0 && options?.caretY !== void 0) {
9881
+ if (preservedRange) {
9882
+ const selection = window.getSelection();
9883
+ selection?.removeAllRanges();
9884
+ selection?.addRange(preservedRange);
9885
+ } else if (options?.caretX !== void 0 && options?.caretY !== void 0) {
9622
9886
  const { caretX, caretY } = options;
9623
9887
  placeCaretAtPoint(el, caretX, caretY);
9624
9888
  requestAnimationFrame(() => {
@@ -9663,6 +9927,7 @@ function OhhwellsBridge() {
9663
9927
  for (const [key, val] of Object.entries(content)) {
9664
9928
  if (key === "__ohw_sections") continue;
9665
9929
  if (applyVideoSettingNode(key, val)) continue;
9930
+ if (applyCarouselNode(key, val)) continue;
9666
9931
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
9667
9932
  if (el.dataset.ohwEditable === "image") {
9668
9933
  const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
@@ -9723,7 +9988,7 @@ function OhhwellsBridge() {
9723
9988
  cancelled = true;
9724
9989
  };
9725
9990
  }, [subdomain, isEditMode]);
9726
- useEffect8(() => {
9991
+ useEffect9(() => {
9727
9992
  if (!subdomain || isEditMode) return;
9728
9993
  let debounceTimer = null;
9729
9994
  let observer = null;
@@ -9736,6 +10001,7 @@ function OhhwellsBridge() {
9736
10001
  for (const [key, val] of Object.entries(content)) {
9737
10002
  if (key === "__ohw_sections") continue;
9738
10003
  if (applyVideoSettingNode(key, val)) continue;
10004
+ if (applyCarouselNode(key, val)) continue;
9739
10005
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
9740
10006
  if (el.dataset.ohwEditable === "image") {
9741
10007
  const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
@@ -9779,10 +10045,10 @@ function OhhwellsBridge() {
9779
10045
  const visible = Boolean(subdomain) && fetchState !== "done";
9780
10046
  el.style.display = visible ? "flex" : "none";
9781
10047
  }, [subdomain, fetchState]);
9782
- useEffect8(() => {
10048
+ useEffect9(() => {
9783
10049
  postToParent2({ type: "ow:navigation", path: pathname });
9784
10050
  }, [pathname, postToParent2]);
9785
- useEffect8(() => {
10051
+ useEffect9(() => {
9786
10052
  if (!isEditMode) return;
9787
10053
  if (linkPopoverSessionRef.current?.intent === "add-nav") return;
9788
10054
  if (document.querySelector("[data-ohw-section-picker]")) return;
@@ -9790,7 +10056,7 @@ function OhhwellsBridge() {
9790
10056
  deselectRef.current();
9791
10057
  deactivateRef.current();
9792
10058
  }, [pathname, isEditMode]);
9793
- useEffect8(() => {
10059
+ useEffect9(() => {
9794
10060
  const contentForNav = () => {
9795
10061
  if (isEditMode) return editContentRef.current;
9796
10062
  if (!subdomain) return {};
@@ -9855,7 +10121,7 @@ function OhhwellsBridge() {
9855
10121
  observer?.disconnect();
9856
10122
  };
9857
10123
  }, [isEditMode, pathname, subdomain, fetchState, resyncSelectedNavigationItem]);
9858
- useEffect8(() => {
10124
+ useEffect9(() => {
9859
10125
  if (!isEditMode) return;
9860
10126
  const measure = () => {
9861
10127
  const h = document.body.scrollHeight;
@@ -9879,7 +10145,7 @@ function OhhwellsBridge() {
9879
10145
  window.removeEventListener("resize", handleResize);
9880
10146
  };
9881
10147
  }, [pathname, isEditMode, postToParent2]);
9882
- useEffect8(() => {
10148
+ useEffect9(() => {
9883
10149
  if (!subdomainFromQuery || isEditMode) return;
9884
10150
  const handleClick = (e) => {
9885
10151
  const anchor = e.target.closest("a");
@@ -9895,7 +10161,7 @@ function OhhwellsBridge() {
9895
10161
  document.addEventListener("click", handleClick, true);
9896
10162
  return () => document.removeEventListener("click", handleClick, true);
9897
10163
  }, [subdomainFromQuery, isEditMode, router]);
9898
- useEffect8(() => {
10164
+ useEffect9(() => {
9899
10165
  if (!isEditMode) {
9900
10166
  editStylesRef.current?.base.remove();
9901
10167
  editStylesRef.current?.forceHover.remove();
@@ -10074,7 +10340,9 @@ function OhhwellsBridge() {
10074
10340
  if (inActive || inActiveNav) {
10075
10341
  e.preventDefault();
10076
10342
  e.stopPropagation();
10077
- if (e.detail < 2) {
10343
+ const selection = window.getSelection();
10344
+ const hasRangeSelection = Boolean(selection && !selection.isCollapsed);
10345
+ if (e.detail < 2 && !hasRangeSelection) {
10078
10346
  placeCaretAtPoint(active, e.clientX, e.clientY);
10079
10347
  refreshActiveCommandsRef.current();
10080
10348
  }
@@ -10958,6 +11226,7 @@ function OhhwellsBridge() {
10958
11226
  continue;
10959
11227
  }
10960
11228
  if (applyVideoSettingNode(key, val)) continue;
11229
+ if (applyCarouselNode(key, val)) continue;
10961
11230
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
10962
11231
  if (el.dataset.ohwEditable === "image") {
10963
11232
  const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
@@ -11227,33 +11496,34 @@ function OhhwellsBridge() {
11227
11496
  const h = document.documentElement.scrollHeight;
11228
11497
  if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
11229
11498
  };
11499
+ let selectionChangeRaf = null;
11500
+ const runSelectionChange = () => {
11501
+ selectionChangeRaf = null;
11502
+ const activeRoot = activeElRef.current;
11503
+ if (!activeRoot) return;
11504
+ const startEl = resolveSelectionStartElement(window.getSelection());
11505
+ const next = startEl ? detectActiveFormats(startEl, activeRoot) : /* @__PURE__ */ new Set();
11506
+ setActiveCommands((prev) => setsEqual(prev, next) ? prev : next);
11507
+ };
11230
11508
  const handleSelectionChange = () => {
11231
- if (!activeElRef.current) return;
11232
- const next = /* @__PURE__ */ new Set();
11233
- for (const cmd of ["bold", "italic", "underline", "strikeThrough", "insertUnorderedList", "insertOrderedList"]) {
11234
- try {
11235
- if (document.queryCommandState(cmd)) next.add(cmd);
11236
- } catch {
11237
- }
11238
- }
11239
- const sel = window.getSelection();
11240
- const anchor = sel?.anchorNode;
11241
- if (anchor) {
11242
- const el = anchor.nodeType === Node.TEXT_NODE ? anchor.parentElement : anchor;
11243
- const block = el?.closest("div, p, h1, h2, h3, h4, h5, h6, li, td, th") ?? el;
11244
- if (block) {
11245
- const align = getComputedStyle(block).textAlign;
11246
- if (align === "center") next.add("justifyCenter");
11247
- else if (align === "right" || align === "end") next.add("justifyRight");
11248
- else next.add("justifyLeft");
11249
- }
11250
- }
11251
- setActiveCommands(next);
11509
+ if (pointerHeldRef.current) return;
11510
+ if (selectionChangeRaf !== null) return;
11511
+ selectionChangeRaf = requestAnimationFrame(runSelectionChange);
11512
+ };
11513
+ const markPointerHeld = (e) => {
11514
+ if (e.button !== 0) return;
11515
+ pointerHeldRef.current = true;
11516
+ };
11517
+ const markPointerReleased = () => {
11518
+ if (!pointerHeldRef.current) return;
11519
+ pointerHeldRef.current = false;
11520
+ handleSelectionChange();
11252
11521
  };
11253
- refreshActiveCommandsRef.current = handleSelectionChange;
11522
+ refreshActiveCommandsRef.current = runSelectionChange;
11254
11523
  const handleDocMouseLeave = () => {
11255
11524
  hoveredImageRef.current = null;
11256
11525
  setMediaHover(null);
11526
+ setCarouselHover(null);
11257
11527
  document.querySelectorAll("[data-ohw-state-hovered]").forEach((el) => el.removeAttribute("data-ohw-state-hovered"));
11258
11528
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
11259
11529
  activeStateElRef.current = null;
@@ -11293,6 +11563,48 @@ function OhhwellsBridge() {
11293
11563
  if (e.data?.type !== "ow:canvas-height" || typeof e.data.height !== "number") return;
11294
11564
  document.documentElement.style.setProperty("--ohw-canvas-h", `${e.data.height}px`);
11295
11565
  };
11566
+ const handleCarouselChange = (e) => {
11567
+ if (e.data?.type !== "ow:carousel-change") return;
11568
+ const { key, images } = e.data;
11569
+ if (!key || !Array.isArray(images)) return;
11570
+ const text = JSON.stringify(images);
11571
+ applyCarouselValue(key, images);
11572
+ editContentRef.current = { ...editContentRef.current, [key]: text };
11573
+ postToParentRef.current({ type: "ow:change", nodes: [{ key, text }] });
11574
+ setCarouselHover(null);
11575
+ };
11576
+ const findCarouselAtPoint = (clientX, clientY) => {
11577
+ const containers = Array.from(document.querySelectorAll(`[${CAROUSEL_ATTR}]`));
11578
+ for (let i = containers.length - 1; i >= 0; i--) {
11579
+ const r2 = containers[i].getBoundingClientRect();
11580
+ if (clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom) {
11581
+ return containers[i];
11582
+ }
11583
+ }
11584
+ return null;
11585
+ };
11586
+ const isPointOverEditable = (scope, clientX, clientY) => {
11587
+ const editables = scope.querySelectorAll("[data-ohw-editable], [data-ohw-href-key]");
11588
+ for (const el of editables) {
11589
+ const r2 = el.getBoundingClientRect();
11590
+ if (clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom) return true;
11591
+ }
11592
+ return false;
11593
+ };
11594
+ const handleCarouselHover = (e) => {
11595
+ const container = findCarouselAtPoint(e.clientX, e.clientY);
11596
+ const scope = container?.closest("[data-ohw-section]") ?? container?.parentElement ?? null;
11597
+ if (!container || !scope || isPointOverEditable(scope, e.clientX, e.clientY)) {
11598
+ setCarouselHover((prev) => prev ? null : prev);
11599
+ return;
11600
+ }
11601
+ const key = container.getAttribute("data-ohw-key") ?? "";
11602
+ if (!key) return;
11603
+ const r2 = getVisibleRect(container);
11604
+ setCarouselHover(
11605
+ (prev) => prev && prev.key === key && prev.rect.top === r2.top && prev.rect.left === r2.left && prev.rect.width === r2.width && prev.rect.height === r2.height ? prev : { key, rect: { top: r2.top, left: r2.left, width: r2.width, height: r2.height } }
11606
+ );
11607
+ };
11296
11608
  const applyToolbarPos = (rect) => {
11297
11609
  const ps = parentScrollRef.current;
11298
11610
  const measuredW = toolbarElRef.current?.offsetWidth || 330;
@@ -11406,6 +11718,7 @@ function OhhwellsBridge() {
11406
11718
  window.addEventListener("message", handleRemoveSchedulingSection);
11407
11719
  window.addEventListener("message", handleImageUrl);
11408
11720
  window.addEventListener("message", handleImageUploading);
11721
+ window.addEventListener("message", handleCarouselChange);
11409
11722
  window.addEventListener("message", handleCanvasHeight);
11410
11723
  window.addEventListener("message", handleParentScroll);
11411
11724
  window.addEventListener("message", handlePointerSync);
@@ -11423,6 +11736,7 @@ function OhhwellsBridge() {
11423
11736
  document.addEventListener("mouseover", handleMouseOver, true);
11424
11737
  document.addEventListener("mouseout", handleMouseOut, true);
11425
11738
  document.addEventListener("mousemove", handleMouseMove, true);
11739
+ document.addEventListener("mousemove", handleCarouselHover, true);
11426
11740
  document.addEventListener("mouseleave", handleDocMouseLeave);
11427
11741
  document.addEventListener("dragover", handleDragOver, true);
11428
11742
  document.addEventListener("dragleave", handleDragLeave, true);
@@ -11438,6 +11752,7 @@ function OhhwellsBridge() {
11438
11752
  document.removeEventListener("mouseover", handleMouseOver, true);
11439
11753
  document.removeEventListener("mouseout", handleMouseOut, true);
11440
11754
  document.removeEventListener("mousemove", handleMouseMove, true);
11755
+ document.removeEventListener("mousemove", handleCarouselHover, true);
11441
11756
  document.removeEventListener("mouseleave", handleDocMouseLeave);
11442
11757
  document.removeEventListener("dragover", handleDragOver, true);
11443
11758
  document.removeEventListener("dragleave", handleDragLeave, true);
@@ -11453,6 +11768,7 @@ function OhhwellsBridge() {
11453
11768
  window.removeEventListener("message", handleRemoveSchedulingSection);
11454
11769
  window.removeEventListener("message", handleImageUrl);
11455
11770
  window.removeEventListener("message", handleImageUploading);
11771
+ window.removeEventListener("message", handleCarouselChange);
11456
11772
  window.removeEventListener("message", handleCanvasHeight);
11457
11773
  window.removeEventListener("message", handleParentScroll);
11458
11774
  window.removeEventListener("resize", handleViewportResize);
@@ -11467,7 +11783,7 @@ function OhhwellsBridge() {
11467
11783
  if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
11468
11784
  };
11469
11785
  }, [isEditMode, refreshStateRules]);
11470
- useEffect8(() => {
11786
+ useEffect9(() => {
11471
11787
  if (!isEditMode) return;
11472
11788
  const THRESHOLD = 10;
11473
11789
  const resolveWasSelected = (el) => {
@@ -11490,7 +11806,6 @@ function OhhwellsBridge() {
11490
11806
  const anchor = getNavigationItemAnchor(target);
11491
11807
  const hrefKey = anchor?.getAttribute("data-ohw-href-key") ?? null;
11492
11808
  if (anchor && isFooterHrefKey(hrefKey)) {
11493
- armFooterPressDrag();
11494
11809
  footerPointerDragRef.current = {
11495
11810
  el: anchor,
11496
11811
  kind: "link",
@@ -11504,7 +11819,6 @@ function OhhwellsBridge() {
11504
11819
  }
11505
11820
  const col = target.closest("[data-ohw-footer-col]");
11506
11821
  if (col && !getNavigationItemAnchor(target)) {
11507
- armFooterPressDrag();
11508
11822
  footerPointerDragRef.current = {
11509
11823
  el: col,
11510
11824
  kind: "column",
@@ -11533,6 +11847,7 @@ function OhhwellsBridge() {
11533
11847
  if (dx * dx + dy * dy < THRESHOLD * THRESHOLD) return;
11534
11848
  e.preventDefault();
11535
11849
  pending.started = true;
11850
+ armFooterPressDrag();
11536
11851
  clearTextSelection();
11537
11852
  try {
11538
11853
  document.body.setPointerCapture(pending.pointerId);
@@ -11586,7 +11901,8 @@ function OhhwellsBridge() {
11586
11901
  }
11587
11902
  } catch {
11588
11903
  }
11589
- if (!pending?.started) {
11904
+ if (!pending) return;
11905
+ if (!pending.started) {
11590
11906
  unlockFooterDragInteraction();
11591
11907
  return;
11592
11908
  }
@@ -11621,7 +11937,7 @@ function OhhwellsBridge() {
11621
11937
  unlockFooterDragInteraction();
11622
11938
  };
11623
11939
  }, [isEditMode]);
11624
- useEffect8(() => {
11940
+ useEffect9(() => {
11625
11941
  const handler = (e) => {
11626
11942
  if (e.data?.type !== "ow:request-schedule-config") return;
11627
11943
  const insertAfterVal = e.data.insertAfter;
@@ -11637,7 +11953,7 @@ function OhhwellsBridge() {
11637
11953
  window.addEventListener("message", handler);
11638
11954
  return () => window.removeEventListener("message", handler);
11639
11955
  }, [processConfigRequest]);
11640
- useEffect8(() => {
11956
+ useEffect9(() => {
11641
11957
  if (!isEditMode) return;
11642
11958
  document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {
11643
11959
  el.removeAttribute("data-ohw-active-state");
@@ -11672,16 +11988,46 @@ function OhhwellsBridge() {
11672
11988
  clearTimeout(timer);
11673
11989
  };
11674
11990
  }, [pathname, isEditMode, refreshStateRules, postToParent2]);
11675
- useEffect8(() => {
11991
+ useEffect9(() => {
11676
11992
  scrollToHashSectionWhenReady();
11677
11993
  const onHashChange = () => scrollToHashSectionWhenReady();
11678
11994
  window.addEventListener("hashchange", onHashChange);
11679
11995
  return () => window.removeEventListener("hashchange", onHashChange);
11680
11996
  }, [pathname]);
11681
11997
  const handleCommand = useCallback4((cmd) => {
11998
+ const el = activeElRef.current;
11999
+ const selBefore = window.getSelection();
12000
+ let savedOffsets = null;
12001
+ if (el && selBefore && selBefore.rangeCount > 0 && !selBefore.isCollapsed) {
12002
+ const r2 = selBefore.getRangeAt(0);
12003
+ if (el.contains(r2.commonAncestorContainer)) {
12004
+ savedOffsets = {
12005
+ start: textOffsetInRoot(el, r2.startContainer, r2.startOffset),
12006
+ end: textOffsetInRoot(el, r2.endContainer, r2.endOffset)
12007
+ };
12008
+ }
12009
+ }
12010
+ document.execCommand("styleWithCSS", false, true);
11682
12011
  document.execCommand(cmd, false);
11683
- activeElRef.current?.focus();
11684
- if (activeElRef.current) setToolbarRect(getEditMeasureEl(activeElRef.current).getBoundingClientRect());
12012
+ if (el && document.activeElement !== el) {
12013
+ el.focus();
12014
+ }
12015
+ const selAfter = window.getSelection();
12016
+ if (el && savedOffsets && selAfter?.isCollapsed) {
12017
+ const start = pointAtTextOffset(el, savedOffsets.start);
12018
+ const end = pointAtTextOffset(el, savedOffsets.end);
12019
+ if (start && end) {
12020
+ try {
12021
+ const range = document.createRange();
12022
+ range.setStart(start.node, start.offset);
12023
+ range.setEnd(end.node, end.offset);
12024
+ selAfter.removeAllRanges();
12025
+ selAfter.addRange(range);
12026
+ } catch {
12027
+ }
12028
+ }
12029
+ }
12030
+ if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
11685
12031
  refreshActiveCommandsRef.current();
11686
12032
  }, []);
11687
12033
  const handleStateChange = useCallback4((state) => {
@@ -11790,6 +12136,12 @@ function OhhwellsBridge() {
11790
12136
  },
11791
12137
  [postToParent2, mediaHover?.elementType]
11792
12138
  );
12139
+ const handleEditCarousel = useCallback4(
12140
+ (key) => {
12141
+ postToParent2({ type: "ow:carousel-open", key, images: readCarouselValue(key) });
12142
+ },
12143
+ [postToParent2]
12144
+ );
11793
12145
  const handleMediaFadeOutComplete = useCallback4((key) => {
11794
12146
  setUploadingRects((prev) => {
11795
12147
  if (!(key in prev)) return prev;
@@ -11821,9 +12173,9 @@ function OhhwellsBridge() {
11821
12173
  [postToParent2]
11822
12174
  );
11823
12175
  return bridgeRoot ? createPortal2(
11824
- /* @__PURE__ */ jsxs13(Fragment5, { children: [
11825
- /* @__PURE__ */ jsx24("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
11826
- Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ jsx24(
12176
+ /* @__PURE__ */ jsxs14(Fragment5, { children: [
12177
+ /* @__PURE__ */ jsx25("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
12178
+ Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ jsx25(
11827
12179
  MediaOverlay,
11828
12180
  {
11829
12181
  hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
@@ -11834,7 +12186,7 @@ function OhhwellsBridge() {
11834
12186
  },
11835
12187
  `uploading-${key}`
11836
12188
  )),
11837
- mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ jsx24(
12189
+ mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ jsx25(
11838
12190
  MediaOverlay,
11839
12191
  {
11840
12192
  hover: mediaHover,
@@ -11843,10 +12195,11 @@ function OhhwellsBridge() {
11843
12195
  onVideoSettingsChange: handleVideoSettingsChange
11844
12196
  }
11845
12197
  ),
11846
- siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ jsx24(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
11847
- siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ jsx24(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
11848
- isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ jsx24(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
11849
- isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ jsx24(
12198
+ carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx25(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
12199
+ siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ jsx25(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
12200
+ siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ jsx25(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
12201
+ isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ jsx25(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
12202
+ isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ jsx25(
11850
12203
  "div",
11851
12204
  {
11852
12205
  className: "pointer-events-none fixed z-2147483646",
@@ -11856,7 +12209,7 @@ function OhhwellsBridge() {
11856
12209
  width: slot.width,
11857
12210
  height: slot.height
11858
12211
  },
11859
- children: /* @__PURE__ */ jsx24(
12212
+ children: /* @__PURE__ */ jsx25(
11860
12213
  DropIndicator,
11861
12214
  {
11862
12215
  direction: slot.direction,
@@ -11867,7 +12220,7 @@ function OhhwellsBridge() {
11867
12220
  },
11868
12221
  `footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
11869
12222
  )),
11870
- isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ jsx24(
12223
+ isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ jsx25(
11871
12224
  "div",
11872
12225
  {
11873
12226
  className: "pointer-events-none fixed z-2147483646",
@@ -11877,7 +12230,7 @@ function OhhwellsBridge() {
11877
12230
  width: slot.width,
11878
12231
  height: slot.height
11879
12232
  },
11880
- children: /* @__PURE__ */ jsx24(
12233
+ children: /* @__PURE__ */ jsx25(
11881
12234
  DropIndicator,
11882
12235
  {
11883
12236
  direction: slot.direction,
@@ -11888,10 +12241,10 @@ function OhhwellsBridge() {
11888
12241
  },
11889
12242
  `nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
11890
12243
  )),
11891
- hoveredNavContainerRect && toolbarVariant !== "select-frame" && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx24(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
11892
- hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ jsx24(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
11893
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer(selectedElRef.current) && /* @__PURE__ */ jsx24(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
11894
- toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ jsx24(
12244
+ hoveredNavContainerRect && toolbarVariant !== "select-frame" && !linkPopover && !isItemDragging && /* @__PURE__ */ jsx25(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
12245
+ hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ jsx25(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
12246
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer(selectedElRef.current) && /* @__PURE__ */ jsx25(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
12247
+ toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ jsx25(
11895
12248
  ItemInteractionLayer,
11896
12249
  {
11897
12250
  rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
@@ -11905,7 +12258,7 @@ function OhhwellsBridge() {
11905
12258
  onItemPointerDown: handleItemChromePointerDown,
11906
12259
  onItemClick: handleItemChromeClick,
11907
12260
  itemDragSurface: !isFooterFrameSelection,
11908
- toolbar: toolbarVariant === "link-action" && !isItemDragging ? /* @__PURE__ */ jsx24(
12261
+ toolbar: toolbarVariant === "link-action" && !isItemDragging ? /* @__PURE__ */ jsx25(
11909
12262
  ItemActionToolbar,
11910
12263
  {
11911
12264
  onEditLink: openLinkPopoverForSelected,
@@ -11918,8 +12271,8 @@ function OhhwellsBridge() {
11918
12271
  ) : void 0
11919
12272
  }
11920
12273
  ),
11921
- toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ jsxs13(Fragment5, { children: [
11922
- /* @__PURE__ */ jsx24(
12274
+ toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ jsxs14(Fragment5, { children: [
12275
+ /* @__PURE__ */ jsx25(
11923
12276
  EditGlowChrome,
11924
12277
  {
11925
12278
  rect: toolbarRect,
@@ -11929,7 +12282,7 @@ function OhhwellsBridge() {
11929
12282
  hideHandle: isItemDragging
11930
12283
  }
11931
12284
  ),
11932
- /* @__PURE__ */ jsx24(
12285
+ /* @__PURE__ */ jsx25(
11933
12286
  FloatingToolbar,
11934
12287
  {
11935
12288
  rect: toolbarRect,
@@ -11942,7 +12295,7 @@ function OhhwellsBridge() {
11942
12295
  }
11943
12296
  )
11944
12297
  ] }),
11945
- maxBadge && /* @__PURE__ */ jsxs13(
12298
+ maxBadge && /* @__PURE__ */ jsxs14(
11946
12299
  "div",
11947
12300
  {
11948
12301
  "data-ohw-max-badge": "",
@@ -11968,7 +12321,7 @@ function OhhwellsBridge() {
11968
12321
  ]
11969
12322
  }
11970
12323
  ),
11971
- toggleState && !linkPopover && /* @__PURE__ */ jsx24(
12324
+ toggleState && !linkPopover && /* @__PURE__ */ jsx25(
11972
12325
  StateToggle,
11973
12326
  {
11974
12327
  rect: toggleState.rect,
@@ -11977,15 +12330,15 @@ function OhhwellsBridge() {
11977
12330
  onStateChange: handleStateChange
11978
12331
  }
11979
12332
  ),
11980
- sectionGap && !linkPopover && /* @__PURE__ */ jsxs13(
12333
+ sectionGap && !linkPopover && /* @__PURE__ */ jsxs14(
11981
12334
  "div",
11982
12335
  {
11983
12336
  "data-ohw-section-insert-line": "",
11984
12337
  className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
11985
12338
  style: { top: sectionGap.y, transform: "translateY(-50%)" },
11986
12339
  children: [
11987
- /* @__PURE__ */ jsx24("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
11988
- /* @__PURE__ */ jsx24(
12340
+ /* @__PURE__ */ jsx25("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
12341
+ /* @__PURE__ */ jsx25(
11989
12342
  Badge,
11990
12343
  {
11991
12344
  className: "px-8 py-1 bg-primary hover:bg-primary text-primary-foreground text-xs font-medium shrink-0 rounded-full cursor-pointer pointer-events-auto",
@@ -12002,11 +12355,11 @@ function OhhwellsBridge() {
12002
12355
  children: "Add Section"
12003
12356
  }
12004
12357
  ),
12005
- /* @__PURE__ */ jsx24("div", { className: "flex-1 bg-primary", style: { height: 3 } })
12358
+ /* @__PURE__ */ jsx25("div", { className: "flex-1 bg-primary", style: { height: 3 } })
12006
12359
  ]
12007
12360
  }
12008
12361
  ),
12009
- linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx24(
12362
+ linkPopover && dialogPortalContainer ? /* @__PURE__ */ jsx25(
12010
12363
  LinkPopover,
12011
12364
  {
12012
12365
  panelRef: linkPopoverPanelRef,
@@ -12054,6 +12407,7 @@ export {
12054
12407
  isValidUrl,
12055
12408
  parseTarget,
12056
12409
  toggleVariants,
12410
+ useOhwCarousel,
12057
12411
  validateUrlInput
12058
12412
  };
12059
12413
  //# sourceMappingURL=index.js.map