@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.cjs CHANGED
@@ -57,12 +57,13 @@ __export(index_exports, {
57
57
  isValidUrl: () => isValidUrl,
58
58
  parseTarget: () => parseTarget,
59
59
  toggleVariants: () => toggleVariants,
60
+ useOhwCarousel: () => useOhwCarousel,
60
61
  validateUrlInput: () => validateUrlInput
61
62
  });
62
63
  module.exports = __toCommonJS(index_exports);
63
64
 
64
65
  // src/OhhwellsBridge.tsx
65
- var import_react9 = __toESM(require("react"), 1);
66
+ var import_react10 = __toESM(require("react"), 1);
66
67
  var import_client = require("react-dom/client");
67
68
  var import_react_dom2 = require("react-dom");
68
69
 
@@ -4904,6 +4905,61 @@ function MediaOverlay({
4904
4905
  ] });
4905
4906
  }
4906
4907
 
4908
+ // src/ui/CarouselOverlay.tsx
4909
+ var import_lucide_react4 = require("lucide-react");
4910
+ var import_jsx_runtime12 = require("react/jsx-runtime");
4911
+ var OVERLAY_BUTTON_STYLE2 = {
4912
+ pointerEvents: "auto",
4913
+ fontFamily: "Inter, sans-serif",
4914
+ fontSize: 12,
4915
+ color: "#000"
4916
+ };
4917
+ function CarouselOverlay({
4918
+ hover,
4919
+ onEdit
4920
+ }) {
4921
+ const { rect } = hover;
4922
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4923
+ "div",
4924
+ {
4925
+ "data-ohw-bridge": "",
4926
+ "data-ohw-carousel-overlay": "",
4927
+ className: "flex cursor-pointer items-center justify-center",
4928
+ style: {
4929
+ position: "fixed",
4930
+ top: rect.top,
4931
+ left: rect.left,
4932
+ width: rect.width,
4933
+ height: rect.height,
4934
+ zIndex: 2147483646,
4935
+ pointerEvents: "auto",
4936
+ boxShadow: "inset 0 0 0 1.5px var(--color-primary)",
4937
+ background: "color-mix(in srgb, var(--color-primary) 20%, transparent)"
4938
+ },
4939
+ onClick: () => onEdit(hover.key),
4940
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
4941
+ Button,
4942
+ {
4943
+ "data-ohw-carousel-overlay": "",
4944
+ variant: "outline",
4945
+ size: "sm",
4946
+ className: "cursor-pointer gap-1.5 hover:bg-background",
4947
+ style: OVERLAY_BUTTON_STYLE2,
4948
+ onMouseDown: (e) => e.preventDefault(),
4949
+ onClick: (e) => {
4950
+ e.stopPropagation();
4951
+ onEdit(hover.key);
4952
+ },
4953
+ children: [
4954
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react4.GalleryHorizontal, { size: 14 }),
4955
+ "Edit gallery"
4956
+ ]
4957
+ }
4958
+ )
4959
+ }
4960
+ );
4961
+ }
4962
+
4907
4963
  // src/OhhwellsBridge.tsx
4908
4964
  var import_react_dom3 = require("react-dom");
4909
4965
  var import_navigation2 = require("next/navigation");
@@ -5189,23 +5245,23 @@ var import_react7 = require("react");
5189
5245
  // src/ui/dialog.tsx
5190
5246
  var React8 = __toESM(require("react"), 1);
5191
5247
  var import_radix_ui5 = require("radix-ui");
5192
- var import_lucide_react4 = require("lucide-react");
5193
- var import_jsx_runtime12 = require("react/jsx-runtime");
5248
+ var import_lucide_react5 = require("lucide-react");
5249
+ var import_jsx_runtime13 = require("react/jsx-runtime");
5194
5250
  function Dialog2({
5195
5251
  ...props
5196
5252
  }) {
5197
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_radix_ui5.Dialog.Root, { "data-slot": "dialog", ...props });
5253
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_radix_ui5.Dialog.Root, { "data-slot": "dialog", ...props });
5198
5254
  }
5199
5255
  function DialogPortal({
5200
5256
  ...props
5201
5257
  }) {
5202
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_radix_ui5.Dialog.Portal, { ...props });
5258
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_radix_ui5.Dialog.Portal, { ...props });
5203
5259
  }
5204
5260
  function DialogOverlay({
5205
5261
  className,
5206
5262
  ...props
5207
5263
  }) {
5208
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5264
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5209
5265
  import_radix_ui5.Dialog.Overlay,
5210
5266
  {
5211
5267
  "data-slot": "dialog-overlay",
@@ -5218,9 +5274,9 @@ function DialogOverlay({
5218
5274
  var DialogContent = React8.forwardRef(
5219
5275
  ({ className, children, showCloseButton = true, container, ...props }, ref) => {
5220
5276
  const positionMode = container ? "absolute" : "fixed";
5221
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(DialogPortal, { container: container ?? void 0, children: [
5222
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(DialogOverlay, { className: cn(positionMode, "inset-0") }),
5223
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
5277
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(DialogPortal, { container: container ?? void 0, children: [
5278
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(DialogOverlay, { className: cn(positionMode, "inset-0") }),
5279
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
5224
5280
  import_radix_ui5.Dialog.Content,
5225
5281
  {
5226
5282
  ref,
@@ -5236,13 +5292,13 @@ var DialogContent = React8.forwardRef(
5236
5292
  ...props,
5237
5293
  children: [
5238
5294
  children,
5239
- showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5295
+ showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5240
5296
  import_radix_ui5.Dialog.Close,
5241
5297
  {
5242
5298
  type: "button",
5243
5299
  className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
5244
5300
  "aria-label": "Close",
5245
- children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react4.X, { size: 16, "aria-hidden": true })
5301
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react5.X, { size: 16, "aria-hidden": true })
5246
5302
  }
5247
5303
  ) : null
5248
5304
  ]
@@ -5256,13 +5312,13 @@ function DialogHeader({
5256
5312
  className,
5257
5313
  ...props
5258
5314
  }) {
5259
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: cn("flex flex-col gap-1.5", className), ...props });
5315
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: cn("flex flex-col gap-1.5", className), ...props });
5260
5316
  }
5261
5317
  function DialogFooter({
5262
5318
  className,
5263
5319
  ...props
5264
5320
  }) {
5265
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5321
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5266
5322
  "div",
5267
5323
  {
5268
5324
  className: cn("flex items-center justify-end gap-2", className),
@@ -5270,7 +5326,7 @@ function DialogFooter({
5270
5326
  }
5271
5327
  );
5272
5328
  }
5273
- var DialogTitle = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5329
+ var DialogTitle = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5274
5330
  import_radix_ui5.Dialog.Title,
5275
5331
  {
5276
5332
  ref,
@@ -5282,7 +5338,7 @@ var DialogTitle = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE
5282
5338
  }
5283
5339
  ));
5284
5340
  DialogTitle.displayName = import_radix_ui5.Dialog.Title.displayName;
5285
- var DialogDescription = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5341
+ var DialogDescription = React8.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5286
5342
  import_radix_ui5.Dialog.Description,
5287
5343
  {
5288
5344
  ref,
@@ -5294,63 +5350,63 @@ DialogDescription.displayName = import_radix_ui5.Dialog.Description.displayName;
5294
5350
  var DialogClose = import_radix_ui5.Dialog.Close;
5295
5351
 
5296
5352
  // src/ui/link-modal/LinkEditorPanel.tsx
5297
- var import_lucide_react8 = require("lucide-react");
5353
+ var import_lucide_react9 = require("lucide-react");
5298
5354
 
5299
5355
  // src/ui/link-modal/DestinationBreadcrumb.tsx
5300
- var import_lucide_react5 = require("lucide-react");
5301
- var import_jsx_runtime13 = require("react/jsx-runtime");
5356
+ var import_lucide_react6 = require("lucide-react");
5357
+ var import_jsx_runtime14 = require("react/jsx-runtime");
5302
5358
  function DestinationBreadcrumb({
5303
5359
  pageTitle,
5304
5360
  sectionLabel
5305
5361
  }) {
5306
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex w-full flex-col gap-2", children: [
5307
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "text-sm font-medium! text-foreground m-0", children: "Destination" }),
5308
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center gap-3", children: [
5309
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center gap-2", children: [
5310
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react5.File, { size: 16, className: "shrink-0 text-foreground", "aria-hidden": true }),
5311
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "text-sm font-medium leading-none text-foreground!", children: pageTitle })
5362
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex w-full flex-col gap-2", children: [
5363
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "text-sm font-medium! text-foreground m-0", children: "Destination" }),
5364
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center gap-3", children: [
5365
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center gap-2", children: [
5366
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react6.File, { size: 16, className: "shrink-0 text-foreground", "aria-hidden": true }),
5367
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "text-sm font-medium leading-none text-foreground!", children: pageTitle })
5312
5368
  ] }),
5313
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5314
- import_lucide_react5.ArrowRight,
5369
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5370
+ import_lucide_react6.ArrowRight,
5315
5371
  {
5316
5372
  size: 16,
5317
5373
  className: "shrink-0 text-muted-foreground",
5318
5374
  "aria-hidden": true
5319
5375
  }
5320
5376
  ),
5321
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
5322
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5323
- import_lucide_react5.GalleryVertical,
5377
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
5378
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5379
+ import_lucide_react6.GalleryVertical,
5324
5380
  {
5325
5381
  size: 16,
5326
5382
  className: "shrink-0 text-foreground",
5327
5383
  "aria-hidden": true
5328
5384
  }
5329
5385
  ),
5330
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "truncate text-sm font-medium leading-none text-foreground", children: sectionLabel })
5386
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "truncate text-sm font-medium leading-none text-foreground", children: sectionLabel })
5331
5387
  ] })
5332
5388
  ] })
5333
5389
  ] });
5334
5390
  }
5335
5391
 
5336
5392
  // src/ui/link-modal/SectionTreeItem.tsx
5337
- var import_lucide_react6 = require("lucide-react");
5338
- var import_jsx_runtime14 = require("react/jsx-runtime");
5393
+ var import_lucide_react7 = require("lucide-react");
5394
+ var import_jsx_runtime15 = require("react/jsx-runtime");
5339
5395
  function SectionTreeItem({
5340
5396
  section,
5341
5397
  onSelect,
5342
5398
  selected
5343
5399
  }) {
5344
5400
  const interactive = Boolean(onSelect);
5345
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex h-9 w-full items-end pl-3", children: [
5346
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5401
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex h-9 w-full items-end pl-3", children: [
5402
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5347
5403
  "div",
5348
5404
  {
5349
5405
  className: "mr-[-1px] h-9 w-2 shrink-0 rounded-bl-sm border-b border-l border-border mb-4",
5350
5406
  "aria-hidden": true
5351
5407
  }
5352
5408
  ),
5353
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
5409
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
5354
5410
  "div",
5355
5411
  {
5356
5412
  role: interactive ? "button" : void 0,
@@ -5368,15 +5424,15 @@ function SectionTreeItem({
5368
5424
  interactive && selected && "border-primary"
5369
5425
  ),
5370
5426
  children: [
5371
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5372
- import_lucide_react6.GalleryVertical,
5427
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5428
+ import_lucide_react7.GalleryVertical,
5373
5429
  {
5374
5430
  size: 16,
5375
5431
  className: "shrink-0 text-foreground",
5376
5432
  "aria-hidden": true
5377
5433
  }
5378
5434
  ),
5379
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "truncate text-sm font-normal leading-5 text-foreground", children: section.label })
5435
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "truncate text-sm font-normal leading-5 text-foreground", children: section.label })
5380
5436
  ]
5381
5437
  }
5382
5438
  )
@@ -5388,10 +5444,10 @@ var import_react4 = require("react");
5388
5444
 
5389
5445
  // src/ui/input.tsx
5390
5446
  var React9 = __toESM(require("react"), 1);
5391
- var import_jsx_runtime15 = require("react/jsx-runtime");
5447
+ var import_jsx_runtime16 = require("react/jsx-runtime");
5392
5448
  var Input = React9.forwardRef(
5393
5449
  ({ className, type, ...props }, ref) => {
5394
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5450
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5395
5451
  "input",
5396
5452
  {
5397
5453
  type,
@@ -5410,9 +5466,9 @@ Input.displayName = "Input";
5410
5466
 
5411
5467
  // src/ui/label.tsx
5412
5468
  var import_radix_ui6 = require("radix-ui");
5413
- var import_jsx_runtime16 = require("react/jsx-runtime");
5469
+ var import_jsx_runtime17 = require("react/jsx-runtime");
5414
5470
  function Label({ className, ...props }) {
5415
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5471
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5416
5472
  import_radix_ui6.Label.Root,
5417
5473
  {
5418
5474
  "data-slot": "label",
@@ -5423,12 +5479,12 @@ function Label({ className, ...props }) {
5423
5479
  }
5424
5480
 
5425
5481
  // src/ui/link-modal/UrlOrPageInput.tsx
5426
- var import_lucide_react7 = require("lucide-react");
5427
- var import_jsx_runtime17 = require("react/jsx-runtime");
5482
+ var import_lucide_react8 = require("lucide-react");
5483
+ var import_jsx_runtime18 = require("react/jsx-runtime");
5428
5484
  function FieldChevron({
5429
5485
  onClick
5430
5486
  }) {
5431
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5487
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5432
5488
  "button",
5433
5489
  {
5434
5490
  type: "button",
@@ -5436,7 +5492,7 @@ function FieldChevron({
5436
5492
  onClick,
5437
5493
  "aria-label": "Open page list",
5438
5494
  tabIndex: -1,
5439
- children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react7.ChevronDown, { size: 16 })
5495
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.ChevronDown, { size: 16 })
5440
5496
  }
5441
5497
  );
5442
5498
  }
@@ -5497,19 +5553,19 @@ function UrlOrPageInput({
5497
5553
  "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]",
5498
5554
  urlError ? "border-destructive shadow-[0_0_0_1px_var(--ohw-destructive)]" : isFocused ? "border-primary shadow-[0_0_0_1px_var(--ohw-primary)]" : "border-input"
5499
5555
  );
5500
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex w-full flex-col gap-2 p-0", children: [
5501
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
5502
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { ref: rootRef, className: "relative w-full", children: [
5503
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { "data-ohw-link-field": true, className: fieldClassName, children: [
5504
- selectedPage ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "flex shrink-0 items-center pr-2", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5505
- import_lucide_react7.File,
5556
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex w-full flex-col gap-2 p-0", children: [
5557
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
5558
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { ref: rootRef, className: "relative w-full", children: [
5559
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { "data-ohw-link-field": true, className: fieldClassName, children: [
5560
+ selectedPage ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex shrink-0 items-center pr-2", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5561
+ import_lucide_react8.File,
5506
5562
  {
5507
5563
  size: 16,
5508
5564
  className: "shrink-0 text-foreground",
5509
5565
  "aria-hidden": true
5510
5566
  }
5511
5567
  ) }) : null,
5512
- readOnly ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "min-w-0 flex-1 truncate text-sm leading-5 text-foreground", children: selectedPage?.title ?? value }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5568
+ readOnly ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "min-w-0 flex-1 truncate text-sm leading-5 text-foreground", children: selectedPage?.title ?? value }) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5513
5569
  Input,
5514
5570
  {
5515
5571
  ref: inputRef,
@@ -5535,7 +5591,7 @@ function UrlOrPageInput({
5535
5591
  )
5536
5592
  }
5537
5593
  ),
5538
- selectedPage && !readOnly ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5594
+ selectedPage && !readOnly ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5539
5595
  "button",
5540
5596
  {
5541
5597
  type: "button",
@@ -5543,26 +5599,26 @@ function UrlOrPageInput({
5543
5599
  onMouseDown: clearSelection,
5544
5600
  "aria-label": "Clear selected page",
5545
5601
  tabIndex: -1,
5546
- children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react7.X, { size: 16, "aria-hidden": true })
5602
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.X, { size: 16, "aria-hidden": true })
5547
5603
  }
5548
5604
  ) : null,
5549
- !readOnly ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(FieldChevron, { onClick: toggleDropdown }) : null
5605
+ !readOnly ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(FieldChevron, { onClick: toggleDropdown }) : null
5550
5606
  ] }),
5551
- dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5607
+ dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5552
5608
  "div",
5553
5609
  {
5554
5610
  "data-ohw-link-page-dropdown": "",
5555
5611
  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",
5556
5612
  onMouseDown: (e) => e.preventDefault(),
5557
- children: filteredPages.map((page) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
5613
+ children: filteredPages.map((page) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
5558
5614
  "button",
5559
5615
  {
5560
5616
  type: "button",
5561
5617
  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",
5562
5618
  onClick: () => onPageSelect(page),
5563
5619
  children: [
5564
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react7.File, { size: 16, className: "shrink-0", "aria-hidden": true }),
5565
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "truncate", children: page.title })
5620
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.File, { size: 16, className: "shrink-0", "aria-hidden": true }),
5621
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "truncate", children: page.title })
5566
5622
  ]
5567
5623
  },
5568
5624
  page.path
@@ -5570,34 +5626,34 @@ function UrlOrPageInput({
5570
5626
  }
5571
5627
  ) : null
5572
5628
  ] }),
5573
- urlError ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-sm font-medium text-destructive", children: urlError }) : null
5629
+ urlError ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "text-sm font-medium text-destructive", children: urlError }) : null
5574
5630
  ] });
5575
5631
  }
5576
5632
 
5577
5633
  // src/ui/link-modal/LinkEditorPanel.tsx
5578
- var import_jsx_runtime18 = require("react/jsx-runtime");
5634
+ var import_jsx_runtime19 = require("react/jsx-runtime");
5579
5635
  function LinkEditorPanel({ state, onClose }) {
5580
5636
  const isCancel = state.secondaryLabel === "Cancel" || state.secondaryLabel === "Back to sections";
5581
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
5582
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DialogClose, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5637
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
5638
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DialogClose, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5583
5639
  "button",
5584
5640
  {
5585
5641
  type: "button",
5586
5642
  className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50 h-7",
5587
5643
  "aria-label": "Close",
5588
5644
  onClick: onClose,
5589
- children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.X, { size: 16, "aria-hidden": true })
5645
+ children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react9.X, { size: 16, "aria-hidden": true })
5590
5646
  }
5591
5647
  ) }),
5592
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DialogHeader, { className: "w-full gap-1.5 p-6 pr-12", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DialogTitle, { className: "m-0 w-full break-words", children: state.title }) }),
5593
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex w-full flex-col gap-3 px-6 pb-8 pt-1", children: [
5594
- state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5648
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DialogHeader, { className: "w-full gap-1.5 p-6 pr-12", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DialogTitle, { className: "m-0 w-full break-words", children: state.title }) }),
5649
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex w-full flex-col gap-3 px-6 pb-8 pt-1", children: [
5650
+ state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5595
5651
  DestinationBreadcrumb,
5596
5652
  {
5597
5653
  pageTitle: state.selectedPage.title,
5598
5654
  sectionLabel: state.selectedSection.label
5599
5655
  }
5600
- ) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5656
+ ) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5601
5657
  UrlOrPageInput,
5602
5658
  {
5603
5659
  value: state.searchValue,
@@ -5610,8 +5666,8 @@ function LinkEditorPanel({ state, onClose }) {
5610
5666
  urlError: state.urlError
5611
5667
  }
5612
5668
  ),
5613
- state.showChooseSection ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex flex-col justify-center gap-2", children: [
5614
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5669
+ state.showChooseSection ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex flex-col justify-center gap-2", children: [
5670
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5615
5671
  Button,
5616
5672
  {
5617
5673
  type: "button",
@@ -5622,15 +5678,15 @@ function LinkEditorPanel({ state, onClose }) {
5622
5678
  children: "Choose a section"
5623
5679
  }
5624
5680
  ),
5625
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
5626
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.Info, { size: 16, className: "shrink-0", "aria-hidden": true }),
5627
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { children: "Pick a section this link should scroll to." })
5681
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
5682
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react9.Info, { size: 16, className: "shrink-0", "aria-hidden": true }),
5683
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { children: "Pick a section this link should scroll to." })
5628
5684
  ] })
5629
5685
  ] }) : null,
5630
- state.showSectionRow && state.selectedSection ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(SectionTreeItem, { section: state.selectedSection, selected: true }) : null
5686
+ state.showSectionRow && state.selectedSection ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(SectionTreeItem, { section: state.selectedSection, selected: true }) : null
5631
5687
  ] }),
5632
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(DialogFooter, { className: "w-full px-6 pb-6", children: [
5633
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5688
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(DialogFooter, { className: "w-full px-6 pb-6", children: [
5689
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5634
5690
  Button,
5635
5691
  {
5636
5692
  type: "button",
@@ -5645,7 +5701,7 @@ function LinkEditorPanel({ state, onClose }) {
5645
5701
  children: state.secondaryLabel
5646
5702
  }
5647
5703
  ),
5648
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5704
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5649
5705
  Button,
5650
5706
  {
5651
5707
  type: "button",
@@ -5666,9 +5722,9 @@ function LinkEditorPanel({ state, onClose }) {
5666
5722
  // src/ui/link-modal/SectionPickerOverlay.tsx
5667
5723
  var import_react5 = require("react");
5668
5724
  var import_react_dom = require("react-dom");
5669
- var import_lucide_react9 = require("lucide-react");
5725
+ var import_lucide_react10 = require("lucide-react");
5670
5726
  var import_navigation = require("next/navigation");
5671
- var import_jsx_runtime19 = require("react/jsx-runtime");
5727
+ var import_jsx_runtime20 = require("react/jsx-runtime");
5672
5728
  var DIM_OVERLAY = "rgba(0, 0, 0, 0.45)";
5673
5729
  function rectsEqual(a, b) {
5674
5730
  if (a.size !== b.size) return false;
@@ -5897,7 +5953,7 @@ function SectionPickerOverlay({
5897
5953
  const portalRoot = typeof document !== "undefined" ? document.querySelector("[data-ohw-bridge-root]") ?? document.body : null;
5898
5954
  if (!portalRoot) return null;
5899
5955
  return (0, import_react_dom.createPortal)(
5900
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
5956
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
5901
5957
  "div",
5902
5958
  {
5903
5959
  "data-ohw-section-picker": "",
@@ -5907,12 +5963,12 @@ function SectionPickerOverlay({
5907
5963
  role: "dialog",
5908
5964
  "aria-label": "Choose a section",
5909
5965
  children: [
5910
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5966
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
5911
5967
  "div",
5912
5968
  {
5913
5969
  className: "pointer-events-auto fixed left-5 z-[2]",
5914
5970
  style: { top: chromeClip.top + 20 },
5915
- children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
5971
+ children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
5916
5972
  Button,
5917
5973
  {
5918
5974
  type: "button",
@@ -5921,14 +5977,14 @@ function SectionPickerOverlay({
5921
5977
  className: "h-8 min-w-0 gap-1 border-border bg-background px-2 py-1.5 shadow-sm hover:bg-muted cursor-pointer",
5922
5978
  onClick: onBack,
5923
5979
  children: [
5924
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react9.ArrowLeft, { className: "size-4 shrink-0", "aria-hidden": true }),
5980
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react10.ArrowLeft, { className: "size-4 shrink-0", "aria-hidden": true }),
5925
5981
  "Back"
5926
5982
  ]
5927
5983
  }
5928
5984
  )
5929
5985
  }
5930
5986
  ),
5931
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5987
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
5932
5988
  "div",
5933
5989
  {
5934
5990
  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",
@@ -5941,7 +5997,7 @@ function SectionPickerOverlay({
5941
5997
  children: "Click on section to select"
5942
5998
  }
5943
5999
  ),
5944
- !isOnTargetPage ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6000
+ !isOnTargetPage ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
5945
6001
  "div",
5946
6002
  {
5947
6003
  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",
@@ -5949,14 +6005,14 @@ function SectionPickerOverlay({
5949
6005
  children: "Loading page preview\u2026"
5950
6006
  }
5951
6007
  ) : null,
5952
- isOnTargetPage && liveSections.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "pointer-events-auto fixed inset-0 z-[1] flex items-center justify-center bg-muted/40", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "text-sm text-muted-foreground", children: "No sections found on this page." }) }) : null,
6008
+ isOnTargetPage && liveSections.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "pointer-events-auto fixed inset-0 z-[1] flex items-center justify-center bg-muted/40", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "text-sm text-muted-foreground", children: "No sections found on this page." }) }) : null,
5953
6009
  isOnTargetPage ? liveSections.map((section) => {
5954
6010
  const rect = rects.get(section.id);
5955
6011
  if (!rect || rect.width <= 0 || rect.height <= 0) return null;
5956
6012
  const isSelected = selectedId === section.id;
5957
6013
  const isHovered = hoveredId === section.id;
5958
6014
  const isLit = isSelected || isHovered;
5959
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
6015
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
5960
6016
  "button",
5961
6017
  {
5962
6018
  type: "button",
@@ -5971,7 +6027,7 @@ function SectionPickerOverlay({
5971
6027
  "aria-label": `Select section ${section.label}`,
5972
6028
  onClick: () => handleSelect(section),
5973
6029
  children: [
5974
- isLit ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6030
+ isLit ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
5975
6031
  "span",
5976
6032
  {
5977
6033
  className: "pointer-events-none absolute",
@@ -5984,13 +6040,13 @@ function SectionPickerOverlay({
5984
6040
  "aria-hidden": true
5985
6041
  }
5986
6042
  ) : null,
5987
- isSelected ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
6043
+ isSelected ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
5988
6044
  "span",
5989
6045
  {
5990
6046
  className: "absolute right-3 top-3 flex size-8 items-center justify-center rounded-full text-white",
5991
6047
  style: { backgroundColor: "var(--ohw-primary, #0885fe)" },
5992
6048
  "aria-hidden": true,
5993
- children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react9.Check, { className: "size-5" })
6049
+ children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react10.Check, { className: "size-5" })
5994
6050
  }
5995
6051
  ) : null
5996
6052
  ]
@@ -6170,7 +6226,7 @@ function useLinkModalState({
6170
6226
  }
6171
6227
 
6172
6228
  // src/ui/link-modal/LinkPopover.tsx
6173
- var import_jsx_runtime20 = require("react/jsx-runtime");
6229
+ var import_jsx_runtime21 = require("react/jsx-runtime");
6174
6230
  function postToParent(data) {
6175
6231
  window.parent?.postMessage(data, "*");
6176
6232
  }
@@ -6266,15 +6322,15 @@ function LinkPopover({
6266
6322
  );
6267
6323
  };
6268
6324
  }, [open, sectionPickerActive]);
6269
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
6270
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6325
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
6326
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6271
6327
  Dialog2,
6272
6328
  {
6273
6329
  open: open && !sectionPickerActive,
6274
6330
  onOpenChange: (next) => {
6275
6331
  if (!next) onClose?.();
6276
6332
  },
6277
- children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6333
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6278
6334
  DialogContent,
6279
6335
  {
6280
6336
  ref: panelRef,
@@ -6284,12 +6340,12 @@ function LinkPopover({
6284
6340
  "data-ohw-bridge": "",
6285
6341
  showCloseButton: false,
6286
6342
  className: "gap-0 p-0 w-full max-w-[448px] pointer-events-auto z-[2147483646] overflow-visible",
6287
- children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(LinkEditorPanel, { state, onClose })
6343
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LinkEditorPanel, { state, onClose })
6288
6344
  }
6289
6345
  )
6290
6346
  }
6291
6347
  ),
6292
- sectionPickerActive && state.selectedPage ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6348
+ sectionPickerActive && state.selectedPage ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6293
6349
  SectionPickerOverlay,
6294
6350
  {
6295
6351
  pagePath: state.selectedPage.path,
@@ -6661,6 +6717,8 @@ function applyNavOrderToContainer(container, order) {
6661
6717
  if (current.length === expected.length && current.every((key, i) => key === expected[i])) {
6662
6718
  return;
6663
6719
  }
6720
+ const lastCurrentLinkEl = current.length > 0 ? findCounterpartByHrefKey(current[current.length - 1], container) : null;
6721
+ const anchor = lastCurrentLinkEl?.parentElement === container ? lastCurrentLinkEl.nextElementSibling : null;
6664
6722
  const seen = /* @__PURE__ */ new Set();
6665
6723
  for (const hrefKey of desired) {
6666
6724
  if (seen.has(hrefKey)) continue;
@@ -6675,7 +6733,9 @@ function applyNavOrderToContainer(container, order) {
6675
6733
  orderedEls.push(el);
6676
6734
  }
6677
6735
  for (const el of orderedEls) {
6678
- if (container.lastElementChild !== el) {
6736
+ if (anchor) {
6737
+ if (el.nextSibling !== anchor) container.insertBefore(el, anchor);
6738
+ } else if (container.lastElementChild !== el) {
6679
6739
  container.appendChild(el);
6680
6740
  }
6681
6741
  }
@@ -7017,6 +7077,11 @@ function reconcileFooterOrderFromContent(content) {
7017
7077
  }
7018
7078
  applyFooterOrder(order);
7019
7079
  }
7080
+ function isRowLayoutColumn(links) {
7081
+ if (links.length < 2) return false;
7082
+ const firstTop = links[0].getBoundingClientRect().top;
7083
+ return links.every((link) => Math.abs(link.getBoundingClientRect().top - firstTop) < 4);
7084
+ }
7020
7085
  function buildLinkDropSlots(column, columnIndex) {
7021
7086
  const links = listFooterLinksInColumn(column);
7022
7087
  const colRect = column.getBoundingClientRect();
@@ -7034,6 +7099,32 @@ function buildLinkDropSlots(column, columnIndex) {
7034
7099
  });
7035
7100
  return slots;
7036
7101
  }
7102
+ if (isRowLayoutColumn(links)) {
7103
+ for (let i = 0; i <= links.length; i++) {
7104
+ let left;
7105
+ if (i === 0) {
7106
+ left = links[0].getBoundingClientRect().left - barThickness / 2;
7107
+ } else if (i === links.length) {
7108
+ const last = links[links.length - 1].getBoundingClientRect();
7109
+ left = last.right - barThickness / 2;
7110
+ } else {
7111
+ const prev = links[i - 1].getBoundingClientRect();
7112
+ const next = links[i].getBoundingClientRect();
7113
+ left = (prev.right + next.left) / 2 - barThickness / 2;
7114
+ }
7115
+ const heightRef = i === 0 ? links[0].getBoundingClientRect() : i === links.length ? links[links.length - 1].getBoundingClientRect() : links[i].getBoundingClientRect();
7116
+ slots.push({
7117
+ insertIndex: i,
7118
+ columnIndex,
7119
+ left,
7120
+ top: heightRef.top,
7121
+ width: barThickness,
7122
+ height: Math.max(heightRef.height, colRect.height * 0.8),
7123
+ direction: "vertical"
7124
+ });
7125
+ }
7126
+ return slots;
7127
+ }
7037
7128
  for (let i = 0; i <= links.length; i++) {
7038
7129
  let top;
7039
7130
  if (i === 0) {
@@ -7117,8 +7208,7 @@ function hitTestLinkDropSlot(clientX, clientY, draggedHrefKey) {
7117
7208
  return true;
7118
7209
  });
7119
7210
  for (const slot of slots) {
7120
- const cy = slot.top + slot.height / 2;
7121
- const dist = Math.abs(clientY - cy) + (inColX ? 0 : 1e3);
7211
+ const dist = slot.direction === "vertical" ? Math.abs(clientX - (slot.left + slot.width / 2)) : Math.abs(clientY - (slot.top + slot.height / 2));
7122
7212
  if (!best || dist < best.dist) best = { slot, dist };
7123
7213
  }
7124
7214
  }
@@ -7162,9 +7252,10 @@ function lockItemDuringDrag() {
7162
7252
  clearTextSelection();
7163
7253
  }
7164
7254
  function unlockItemDragInteraction() {
7255
+ const wasDragging = document.documentElement.hasAttribute("data-ohw-item-dragging");
7165
7256
  document.documentElement.removeAttribute("data-ohw-footer-press-drag");
7166
7257
  document.documentElement.removeAttribute("data-ohw-item-dragging");
7167
- clearTextSelection();
7258
+ if (wasDragging) clearTextSelection();
7168
7259
  }
7169
7260
  var armFooterPressDrag = armItemPressDrag;
7170
7261
  var lockFooterDuringDrag = lockItemDuringDrag;
@@ -7541,7 +7632,6 @@ function useNavItemDrag({
7541
7632
  const hrefKey = anchor?.getAttribute("data-ohw-href-key") ?? null;
7542
7633
  if (!anchor || !isNavbarHrefKey(hrefKey)) return;
7543
7634
  if (isNavbarButton3(anchor) || isDragHandleDisabled2(anchor)) return;
7544
- armItemPressDrag();
7545
7635
  navPointerDragRef.current = {
7546
7636
  el: anchor,
7547
7637
  startX: e.clientX,
@@ -7568,6 +7658,7 @@ function useNavItemDrag({
7568
7658
  if (dx * dx + dy * dy < THRESHOLD * THRESHOLD) return;
7569
7659
  e.preventDefault();
7570
7660
  pending.started = true;
7661
+ armItemPressDrag();
7571
7662
  clearTextSelection();
7572
7663
  try {
7573
7664
  document.body.setPointerCapture(pending.pointerId);
@@ -7595,7 +7686,8 @@ function useNavItemDrag({
7595
7686
  }
7596
7687
  } catch {
7597
7688
  }
7598
- if (!pending?.started) {
7689
+ if (!pending) return;
7690
+ if (!pending.started) {
7599
7691
  unlockItemDragInteraction();
7600
7692
  return;
7601
7693
  }
@@ -7647,7 +7739,6 @@ function useNavItemDrag({
7647
7739
  const hrefKey = selected.getAttribute("data-ohw-href-key");
7648
7740
  if (!hrefKey || !isNavbarHrefKey(hrefKey)) return false;
7649
7741
  if (isNavbarButton3(selected) || isDragHandleDisabled2(selected)) return false;
7650
- armItemPressDrag();
7651
7742
  navPointerDragRef.current = {
7652
7743
  el: selected,
7653
7744
  startX: clientX,
@@ -7673,15 +7764,99 @@ function useNavItemDrag({
7673
7764
  };
7674
7765
  }
7675
7766
 
7767
+ // src/lib/carousel.ts
7768
+ var import_react9 = require("react");
7769
+ var CAROUSEL_ATTR = "data-ohw-carousel";
7770
+ var CAROUSEL_VALUE_ATTR = "data-ohw-carousel-value";
7771
+ var CAROUSEL_SLIDE_ATTR = "data-ohw-carousel-slide";
7772
+ var CAROUSEL_EVENT = "ohw:carousel-change";
7773
+ function listCarouselKeys() {
7774
+ const keys = /* @__PURE__ */ new Set();
7775
+ document.querySelectorAll(`[${CAROUSEL_ATTR}]`).forEach((el) => {
7776
+ const key = el.getAttribute("data-ohw-key");
7777
+ if (key) keys.add(key);
7778
+ });
7779
+ return [...keys];
7780
+ }
7781
+ function containersForKey(key) {
7782
+ return Array.from(
7783
+ document.querySelectorAll(`[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`)
7784
+ );
7785
+ }
7786
+ function isCarouselKey(key) {
7787
+ return containersForKey(key).length > 0;
7788
+ }
7789
+ function parseSlides(raw) {
7790
+ if (!raw) return [];
7791
+ try {
7792
+ const parsed = JSON.parse(raw);
7793
+ if (!Array.isArray(parsed)) return [];
7794
+ return parsed.filter((s) => Boolean(s) && typeof s === "object").map((s) => ({ src: String(s.src ?? ""), alt: String(s.alt ?? "") }));
7795
+ } catch {
7796
+ return [];
7797
+ }
7798
+ }
7799
+ function readCarouselValue(key) {
7800
+ const container = containersForKey(key)[0];
7801
+ if (!container) return [];
7802
+ const fromAttr = parseSlides(container.getAttribute(CAROUSEL_VALUE_ATTR));
7803
+ if (fromAttr.length > 0) return fromAttr;
7804
+ return Array.from(container.querySelectorAll(`[${CAROUSEL_SLIDE_ATTR}]`)).filter((slide) => slide.closest(`[${CAROUSEL_ATTR}]`) === container).sort((a, b) => slideIndex(a) - slideIndex(b)).map((slide) => {
7805
+ const img = slide instanceof HTMLImageElement ? slide : slide.querySelector("img");
7806
+ return { src: img?.src ?? "", alt: img?.alt ?? "" };
7807
+ });
7808
+ }
7809
+ function slideIndex(el) {
7810
+ const raw = el.getAttribute(CAROUSEL_SLIDE_ATTR);
7811
+ const n = raw ? parseInt(raw, 10) : NaN;
7812
+ return Number.isFinite(n) ? n : 0;
7813
+ }
7814
+ function applyCarouselValue(key, slides) {
7815
+ const value = JSON.stringify(slides);
7816
+ for (const container of containersForKey(key)) {
7817
+ if (container.getAttribute(CAROUSEL_VALUE_ATTR) === value) continue;
7818
+ container.setAttribute(CAROUSEL_VALUE_ATTR, value);
7819
+ container.dispatchEvent(
7820
+ new CustomEvent(CAROUSEL_EVENT, { detail: { images: slides } })
7821
+ );
7822
+ }
7823
+ }
7824
+ function applyCarouselNode(key, val) {
7825
+ if (!isCarouselKey(key)) return false;
7826
+ applyCarouselValue(key, parseSlides(val));
7827
+ return true;
7828
+ }
7829
+ function useOhwCarousel(key, initial) {
7830
+ const [images, setImages] = (0, import_react9.useState)(initial);
7831
+ (0, import_react9.useEffect)(() => {
7832
+ const el = document.querySelector(
7833
+ `[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`
7834
+ );
7835
+ if (!el) return;
7836
+ const onChange = (e) => {
7837
+ const detail = e.detail;
7838
+ if (Array.isArray(detail?.images)) setImages(detail.images);
7839
+ };
7840
+ el.addEventListener(CAROUSEL_EVENT, onChange);
7841
+ return () => el.removeEventListener(CAROUSEL_EVENT, onChange);
7842
+ }, [key]);
7843
+ const bind = {
7844
+ [CAROUSEL_ATTR]: "",
7845
+ "data-ohw-key": key,
7846
+ [CAROUSEL_VALUE_ATTR]: JSON.stringify(images)
7847
+ };
7848
+ return { images, setImages, bind };
7849
+ }
7850
+
7676
7851
  // src/ui/navbar-container-chrome.tsx
7677
- var import_lucide_react10 = require("lucide-react");
7678
- var import_jsx_runtime21 = require("react/jsx-runtime");
7852
+ var import_lucide_react11 = require("lucide-react");
7853
+ var import_jsx_runtime22 = require("react/jsx-runtime");
7679
7854
  function NavbarContainerChrome({
7680
7855
  rect,
7681
7856
  onAdd
7682
7857
  }) {
7683
7858
  const chromeGap = 6;
7684
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7859
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
7685
7860
  "div",
7686
7861
  {
7687
7862
  "data-ohw-navbar-container-chrome": "",
@@ -7693,7 +7868,7 @@ function NavbarContainerChrome({
7693
7868
  width: rect.width + chromeGap * 2,
7694
7869
  height: rect.height + chromeGap * 2
7695
7870
  },
7696
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
7871
+ children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
7697
7872
  "button",
7698
7873
  {
7699
7874
  type: "button",
@@ -7710,7 +7885,7 @@ function NavbarContainerChrome({
7710
7885
  e.stopPropagation();
7711
7886
  onAdd();
7712
7887
  },
7713
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react10.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
7888
+ children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react11.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
7714
7889
  }
7715
7890
  )
7716
7891
  }
@@ -7719,7 +7894,7 @@ function NavbarContainerChrome({
7719
7894
 
7720
7895
  // src/ui/drop-indicator.tsx
7721
7896
  var React10 = __toESM(require("react"), 1);
7722
- var import_jsx_runtime22 = require("react/jsx-runtime");
7897
+ var import_jsx_runtime23 = require("react/jsx-runtime");
7723
7898
  var dropIndicatorVariants = cva(
7724
7899
  "ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
7725
7900
  {
@@ -7743,7 +7918,7 @@ var dropIndicatorVariants = cva(
7743
7918
  );
7744
7919
  var DropIndicator = React10.forwardRef(
7745
7920
  ({ className, direction, state, ...props }, ref) => {
7746
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
7921
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
7747
7922
  "div",
7748
7923
  {
7749
7924
  ref,
@@ -7760,7 +7935,7 @@ var DropIndicator = React10.forwardRef(
7760
7935
  DropIndicator.displayName = "DropIndicator";
7761
7936
 
7762
7937
  // src/ui/badge.tsx
7763
- var import_jsx_runtime23 = require("react/jsx-runtime");
7938
+ var import_jsx_runtime24 = require("react/jsx-runtime");
7764
7939
  var badgeVariants = cva(
7765
7940
  "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",
7766
7941
  {
@@ -7778,12 +7953,12 @@ var badgeVariants = cva(
7778
7953
  }
7779
7954
  );
7780
7955
  function Badge({ className, variant, ...props }) {
7781
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
7956
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
7782
7957
  }
7783
7958
 
7784
7959
  // src/OhhwellsBridge.tsx
7785
- var import_lucide_react11 = require("lucide-react");
7786
- var import_jsx_runtime24 = require("react/jsx-runtime");
7960
+ var import_lucide_react12 = require("lucide-react");
7961
+ var import_jsx_runtime25 = require("react/jsx-runtime");
7787
7962
  var PRIMARY2 = "#0885FE";
7788
7963
  var IMAGE_FADE_MS = 300;
7789
7964
  function runOpacityFade(el, onDone) {
@@ -7962,7 +8137,7 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
7962
8137
  const root = (0, import_client.createRoot)(container);
7963
8138
  (0, import_react_dom2.flushSync)(() => {
7964
8139
  root.render(
7965
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
8140
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
7966
8141
  SchedulingWidget,
7967
8142
  {
7968
8143
  notifyOnConnect,
@@ -8080,6 +8255,9 @@ function collectEditableNodes(extraContent) {
8080
8255
  nodes.push({ key: `${key}${VIDEO_AUTOPLAY_SUFFIX}`, type: "video-setting", text: String(video.autoplay) });
8081
8256
  nodes.push({ key: `${key}${VIDEO_MUTED_SUFFIX}`, type: "video-setting", text: String(video.muted) });
8082
8257
  });
8258
+ for (const key of listCarouselKeys()) {
8259
+ nodes.push({ key, type: "carousel", text: JSON.stringify(readCarouselValue(key)) });
8260
+ }
8083
8261
  const seen = /* @__PURE__ */ new Set();
8084
8262
  return nodes.filter((node) => {
8085
8263
  if (!node.key) return true;
@@ -8492,9 +8670,16 @@ function sanitizeHtml(html) {
8492
8670
  if (!SAFE_TAGS.has(el.tagName)) {
8493
8671
  parent.replaceChild(document.createTextNode(el.textContent ?? ""), el);
8494
8672
  } else {
8495
- const textAlign = el.style?.textAlign || el.getAttribute("align") || "";
8673
+ const htmlEl = el;
8674
+ const textAlign = htmlEl.style?.textAlign || el.getAttribute("align") || "";
8675
+ const fontWeight = htmlEl.style?.fontWeight || "";
8676
+ const fontStyle = htmlEl.style?.fontStyle || "";
8677
+ const textDecorationLine = htmlEl.style?.textDecorationLine || htmlEl.style?.textDecoration || "";
8496
8678
  for (const attr of Array.from(el.attributes)) el.removeAttribute(attr.name);
8497
- if (textAlign) el.style.textAlign = textAlign;
8679
+ if (textAlign) htmlEl.style.textAlign = textAlign;
8680
+ if (fontWeight) htmlEl.style.fontWeight = fontWeight;
8681
+ if (fontStyle) htmlEl.style.fontStyle = fontStyle;
8682
+ if (textDecorationLine) htmlEl.style.textDecorationLine = textDecorationLine;
8498
8683
  walk(el);
8499
8684
  }
8500
8685
  }
@@ -8541,7 +8726,7 @@ function EditGlowChrome({
8541
8726
  hideHandle = false
8542
8727
  }) {
8543
8728
  const GAP = SELECTION_CHROME_GAP2;
8544
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
8729
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
8545
8730
  "div",
8546
8731
  {
8547
8732
  ref: elRef,
@@ -8556,7 +8741,7 @@ function EditGlowChrome({
8556
8741
  zIndex: 2147483646
8557
8742
  },
8558
8743
  children: [
8559
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
8744
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
8560
8745
  "div",
8561
8746
  {
8562
8747
  style: {
@@ -8569,7 +8754,7 @@ function EditGlowChrome({
8569
8754
  }
8570
8755
  }
8571
8756
  ),
8572
- reorderHrefKey && !hideHandle && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
8757
+ reorderHrefKey && !hideHandle && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
8573
8758
  "div",
8574
8759
  {
8575
8760
  "data-ohw-drag-handle-container": "",
@@ -8581,7 +8766,7 @@ function EditGlowChrome({
8581
8766
  transform: "translate(calc(-100% - 7px), -50%)",
8582
8767
  pointerEvents: dragDisabled ? "none" : "auto"
8583
8768
  },
8584
- children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
8769
+ children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
8585
8770
  DragHandle,
8586
8771
  {
8587
8772
  "aria-label": `Reorder ${reorderHrefKey}`,
@@ -8682,6 +8867,79 @@ function resolveItemInteractionState(rect, parentScroll) {
8682
8867
  const { transform } = calcToolbarPos(rect, parentScroll, 120);
8683
8868
  return transform.includes("translateY(-100%)") ? "active-top" : "active-bottom";
8684
8869
  }
8870
+ function resolveSelectionStartElement(sel) {
8871
+ if (!sel || sel.rangeCount === 0) return null;
8872
+ const range = sel.getRangeAt(0);
8873
+ let startNode = range.startContainer;
8874
+ if (startNode.nodeType === Node.ELEMENT_NODE) {
8875
+ const el = startNode;
8876
+ startNode = el.childNodes[range.startOffset] ?? el.childNodes[range.startOffset - 1] ?? el;
8877
+ }
8878
+ return startNode.nodeType === Node.TEXT_NODE ? startNode.parentElement : startNode;
8879
+ }
8880
+ function detectActiveFormats(startEl, activeRoot) {
8881
+ const formats = /* @__PURE__ */ new Set();
8882
+ const cs = getComputedStyle(startEl);
8883
+ const weight = parseInt(cs.fontWeight, 10);
8884
+ let hasBold = cs.fontWeight === "bold" || !Number.isNaN(weight) && weight >= 600;
8885
+ let hasItalic = cs.fontStyle === "italic" || cs.fontStyle === "oblique";
8886
+ let hasUnderline = false;
8887
+ let hasStrike = false;
8888
+ let hasUl = false;
8889
+ let hasOl = false;
8890
+ for (let el = startEl; el; el = el.parentElement) {
8891
+ if (el.tagName === "B" || el.tagName === "STRONG") hasBold = true;
8892
+ if (el.tagName === "I" || el.tagName === "EM") hasItalic = true;
8893
+ const decoration = getComputedStyle(el).textDecorationLine;
8894
+ if (decoration.includes("underline") || el.tagName === "U" || el.tagName === "INS") hasUnderline = true;
8895
+ if (decoration.includes("line-through") || el.tagName === "S" || el.tagName === "STRIKE" || el.tagName === "DEL") hasStrike = true;
8896
+ if (el.tagName === "UL") hasUl = true;
8897
+ if (el.tagName === "OL") hasOl = true;
8898
+ if (el === activeRoot) break;
8899
+ }
8900
+ if (hasBold) formats.add("bold");
8901
+ if (hasItalic) formats.add("italic");
8902
+ if (hasUnderline) formats.add("underline");
8903
+ if (hasStrike) formats.add("strikeThrough");
8904
+ if (hasUl) formats.add("insertUnorderedList");
8905
+ if (hasOl) formats.add("insertOrderedList");
8906
+ const block = startEl.closest("div, p, h1, h2, h3, h4, h5, h6, li, td, th") ?? startEl;
8907
+ const align = getComputedStyle(block).textAlign;
8908
+ if (align === "center") formats.add("justifyCenter");
8909
+ else if (align === "right" || align === "end") formats.add("justifyRight");
8910
+ else formats.add("justifyLeft");
8911
+ return formats;
8912
+ }
8913
+ function setsEqual(a, b) {
8914
+ if (a.size !== b.size) return false;
8915
+ for (const item of a) {
8916
+ if (!b.has(item)) return false;
8917
+ }
8918
+ return true;
8919
+ }
8920
+ function textOffsetInRoot(root, node, offset) {
8921
+ const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
8922
+ let total = 0;
8923
+ let current;
8924
+ while (current = walker.nextNode()) {
8925
+ if (current === node) return total + offset;
8926
+ total += (current.textContent ?? "").length;
8927
+ }
8928
+ return total;
8929
+ }
8930
+ function pointAtTextOffset(root, targetOffset) {
8931
+ const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
8932
+ let total = 0;
8933
+ let current;
8934
+ let last = null;
8935
+ while (current = walker.nextNode()) {
8936
+ const len = (current.textContent ?? "").length;
8937
+ if (total + len >= targetOffset) return { node: current, offset: targetOffset - total };
8938
+ total += len;
8939
+ last = current;
8940
+ }
8941
+ return last ? { node: last, offset: (last.textContent ?? "").length } : null;
8942
+ }
8685
8943
  function FloatingToolbar({
8686
8944
  rect,
8687
8945
  parentScroll,
@@ -8691,9 +8949,9 @@ function FloatingToolbar({
8691
8949
  showEditLink,
8692
8950
  onEditLink
8693
8951
  }) {
8694
- const localRef = import_react9.default.useRef(null);
8695
- const [measuredW, setMeasuredW] = import_react9.default.useState(330);
8696
- const setRefs = import_react9.default.useCallback(
8952
+ const localRef = import_react10.default.useRef(null);
8953
+ const [measuredW, setMeasuredW] = import_react10.default.useState(330);
8954
+ const setRefs = import_react10.default.useCallback(
8697
8955
  (node) => {
8698
8956
  localRef.current = node;
8699
8957
  if (typeof elRef === "function") elRef(node);
@@ -8705,7 +8963,7 @@ function FloatingToolbar({
8705
8963
  },
8706
8964
  [elRef]
8707
8965
  );
8708
- import_react9.default.useLayoutEffect(() => {
8966
+ import_react10.default.useLayoutEffect(() => {
8709
8967
  const node = localRef.current;
8710
8968
  if (!node) return;
8711
8969
  const update = () => {
@@ -8718,7 +8976,7 @@ function FloatingToolbar({
8718
8976
  return () => ro.disconnect();
8719
8977
  }, [showEditLink, activeCommands]);
8720
8978
  const { top, left, transform } = calcToolbarPos(rect, parentScroll, measuredW);
8721
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
8979
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
8722
8980
  "div",
8723
8981
  {
8724
8982
  ref: setRefs,
@@ -8730,12 +8988,12 @@ function FloatingToolbar({
8730
8988
  zIndex: 2147483647,
8731
8989
  pointerEvents: "auto"
8732
8990
  },
8733
- children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(CustomToolbar, { children: [
8734
- TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react9.default.Fragment, { children: [
8735
- gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(CustomToolbarDivider, {}),
8991
+ children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(CustomToolbar, { children: [
8992
+ TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react10.default.Fragment, { children: [
8993
+ gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(CustomToolbarDivider, {}),
8736
8994
  btns.map((btn) => {
8737
8995
  const isActive = activeCommands.has(btn.cmd);
8738
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
8996
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
8739
8997
  CustomToolbarButton,
8740
8998
  {
8741
8999
  title: btn.title,
@@ -8744,7 +9002,7 @@ function FloatingToolbar({
8744
9002
  e.preventDefault();
8745
9003
  onCommand(btn.cmd);
8746
9004
  },
8747
- children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
9005
+ children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
8748
9006
  "svg",
8749
9007
  {
8750
9008
  width: "16",
@@ -8765,7 +9023,7 @@ function FloatingToolbar({
8765
9023
  );
8766
9024
  })
8767
9025
  ] }, gi)),
8768
- showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
9026
+ showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
8769
9027
  CustomToolbarButton,
8770
9028
  {
8771
9029
  type: "button",
@@ -8779,7 +9037,7 @@ function FloatingToolbar({
8779
9037
  e.preventDefault();
8780
9038
  e.stopPropagation();
8781
9039
  },
8782
- children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react11.Link, { className: "size-4 shrink-0", "aria-hidden": true })
9040
+ children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react12.Link, { className: "size-4 shrink-0", "aria-hidden": true })
8783
9041
  }
8784
9042
  ) : null
8785
9043
  ] })
@@ -8796,7 +9054,7 @@ function StateToggle({
8796
9054
  states,
8797
9055
  onStateChange
8798
9056
  }) {
8799
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
9057
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
8800
9058
  ToggleGroup,
8801
9059
  {
8802
9060
  "data-ohw-state-toggle": "",
@@ -8810,7 +9068,7 @@ function StateToggle({
8810
9068
  left: rect.right - 8,
8811
9069
  transform: "translateX(-100%)"
8812
9070
  },
8813
- children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
9071
+ children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
8814
9072
  }
8815
9073
  );
8816
9074
  }
@@ -8837,8 +9095,8 @@ function OhhwellsBridge() {
8837
9095
  const router = (0, import_navigation2.useRouter)();
8838
9096
  const searchParams = (0, import_navigation2.useSearchParams)();
8839
9097
  const isEditMode = isEditSessionActive();
8840
- const [bridgeRoot, setBridgeRoot] = (0, import_react9.useState)(null);
8841
- (0, import_react9.useEffect)(() => {
9098
+ const [bridgeRoot, setBridgeRoot] = (0, import_react10.useState)(null);
9099
+ (0, import_react10.useEffect)(() => {
8842
9100
  const figtreeFontId = "ohw-figtree-font";
8843
9101
  if (!document.getElementById(figtreeFontId)) {
8844
9102
  const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
@@ -8866,97 +9124,99 @@ function OhhwellsBridge() {
8866
9124
  const subdomainFromQuery = searchParams.get("subdomain");
8867
9125
  const subdomain = resolveSubdomain(subdomainFromQuery);
8868
9126
  useLinkHrefGuardian(pathname, subdomain, isEditMode);
8869
- const postToParent2 = (0, import_react9.useCallback)((data) => {
9127
+ const postToParent2 = (0, import_react10.useCallback)((data) => {
8870
9128
  if (typeof window !== "undefined" && window.parent !== window) {
8871
9129
  window.parent.postMessage(data, "*");
8872
9130
  }
8873
9131
  }, []);
8874
- const [fetchState, setFetchState] = (0, import_react9.useState)("idle");
8875
- const autoSaveTimers = (0, import_react9.useRef)(/* @__PURE__ */ new Map());
8876
- const activeElRef = (0, import_react9.useRef)(null);
8877
- const selectedElRef = (0, import_react9.useRef)(null);
8878
- const selectedHrefKeyRef = (0, import_react9.useRef)(null);
8879
- const selectedFooterColAttrRef = (0, import_react9.useRef)(null);
8880
- const originalContentRef = (0, import_react9.useRef)(null);
8881
- const activeStateElRef = (0, import_react9.useRef)(null);
8882
- const parentScrollRef = (0, import_react9.useRef)(null);
8883
- const visibleViewportRef = (0, import_react9.useRef)(null);
8884
- const [dialogPortalContainer, setDialogPortalContainer] = (0, import_react9.useState)(null);
8885
- const attachVisibleViewport = (0, import_react9.useCallback)((node) => {
9132
+ const [fetchState, setFetchState] = (0, import_react10.useState)("idle");
9133
+ const autoSaveTimers = (0, import_react10.useRef)(/* @__PURE__ */ new Map());
9134
+ const activeElRef = (0, import_react10.useRef)(null);
9135
+ const pointerHeldRef = (0, import_react10.useRef)(false);
9136
+ const selectedElRef = (0, import_react10.useRef)(null);
9137
+ const selectedHrefKeyRef = (0, import_react10.useRef)(null);
9138
+ const selectedFooterColAttrRef = (0, import_react10.useRef)(null);
9139
+ const originalContentRef = (0, import_react10.useRef)(null);
9140
+ const activeStateElRef = (0, import_react10.useRef)(null);
9141
+ const parentScrollRef = (0, import_react10.useRef)(null);
9142
+ const visibleViewportRef = (0, import_react10.useRef)(null);
9143
+ const [dialogPortalContainer, setDialogPortalContainer] = (0, import_react10.useState)(null);
9144
+ const attachVisibleViewport = (0, import_react10.useCallback)((node) => {
8886
9145
  visibleViewportRef.current = node;
8887
9146
  setDialogPortalContainer(node);
8888
9147
  if (node) applyVisibleViewport(node, parentScrollRef.current);
8889
9148
  }, []);
8890
- const toolbarElRef = (0, import_react9.useRef)(null);
8891
- const glowElRef = (0, import_react9.useRef)(null);
8892
- const hoveredImageRef = (0, import_react9.useRef)(null);
8893
- const hoveredImageHasTextOverlapRef = (0, import_react9.useRef)(false);
8894
- const dragOverElRef = (0, import_react9.useRef)(null);
8895
- const [mediaHover, setMediaHover] = (0, import_react9.useState)(null);
8896
- const [uploadingRects, setUploadingRects] = (0, import_react9.useState)({});
8897
- const hoveredGapRef = (0, import_react9.useRef)(null);
8898
- const imageUnhoverTimerRef = (0, import_react9.useRef)(null);
8899
- const imageShowTimerRef = (0, import_react9.useRef)(null);
8900
- const editStylesRef = (0, import_react9.useRef)(null);
8901
- const activateRef = (0, import_react9.useRef)(() => {
9149
+ const toolbarElRef = (0, import_react10.useRef)(null);
9150
+ const glowElRef = (0, import_react10.useRef)(null);
9151
+ const hoveredImageRef = (0, import_react10.useRef)(null);
9152
+ const hoveredImageHasTextOverlapRef = (0, import_react10.useRef)(false);
9153
+ const dragOverElRef = (0, import_react10.useRef)(null);
9154
+ const [mediaHover, setMediaHover] = (0, import_react10.useState)(null);
9155
+ const [carouselHover, setCarouselHover] = (0, import_react10.useState)(null);
9156
+ const [uploadingRects, setUploadingRects] = (0, import_react10.useState)({});
9157
+ const hoveredGapRef = (0, import_react10.useRef)(null);
9158
+ const imageUnhoverTimerRef = (0, import_react10.useRef)(null);
9159
+ const imageShowTimerRef = (0, import_react10.useRef)(null);
9160
+ const editStylesRef = (0, import_react10.useRef)(null);
9161
+ const activateRef = (0, import_react10.useRef)(() => {
8902
9162
  });
8903
- const deactivateRef = (0, import_react9.useRef)(() => {
9163
+ const deactivateRef = (0, import_react10.useRef)(() => {
8904
9164
  });
8905
- const selectRef = (0, import_react9.useRef)(() => {
9165
+ const selectRef = (0, import_react10.useRef)(() => {
8906
9166
  });
8907
- const selectFrameRef = (0, import_react9.useRef)(() => {
9167
+ const selectFrameRef = (0, import_react10.useRef)(() => {
8908
9168
  });
8909
- const deselectRef = (0, import_react9.useRef)(() => {
9169
+ const deselectRef = (0, import_react10.useRef)(() => {
8910
9170
  });
8911
- const reselectNavigationItemRef = (0, import_react9.useRef)(() => {
9171
+ const reselectNavigationItemRef = (0, import_react10.useRef)(() => {
8912
9172
  });
8913
- const commitNavigationTextEditRef = (0, import_react9.useRef)(() => {
9173
+ const commitNavigationTextEditRef = (0, import_react10.useRef)(() => {
8914
9174
  });
8915
- const refreshActiveCommandsRef = (0, import_react9.useRef)(() => {
9175
+ const refreshActiveCommandsRef = (0, import_react10.useRef)(() => {
8916
9176
  });
8917
- const postToParentRef = (0, import_react9.useRef)(postToParent2);
9177
+ const postToParentRef = (0, import_react10.useRef)(postToParent2);
8918
9178
  postToParentRef.current = postToParent2;
8919
- const sectionsLoadedRef = (0, import_react9.useRef)(false);
8920
- const pendingScheduleConfigRequests = (0, import_react9.useRef)([]);
8921
- const [toolbarRect, setToolbarRect] = (0, import_react9.useState)(null);
8922
- const [toolbarVariant, setToolbarVariant] = (0, import_react9.useState)("none");
8923
- const toolbarVariantRef = (0, import_react9.useRef)("none");
9179
+ const sectionsLoadedRef = (0, import_react10.useRef)(false);
9180
+ const pendingScheduleConfigRequests = (0, import_react10.useRef)([]);
9181
+ const [toolbarRect, setToolbarRect] = (0, import_react10.useState)(null);
9182
+ const [toolbarVariant, setToolbarVariant] = (0, import_react10.useState)("none");
9183
+ const toolbarVariantRef = (0, import_react10.useRef)("none");
8924
9184
  toolbarVariantRef.current = toolbarVariant;
8925
- const [selectedIsCta, setSelectedIsCta] = (0, import_react9.useState)(false);
8926
- const [reorderHrefKey, setReorderHrefKey] = (0, import_react9.useState)(null);
8927
- const [reorderDragDisabled, setReorderDragDisabled] = (0, import_react9.useState)(false);
8928
- const [toggleState, setToggleState] = (0, import_react9.useState)(null);
8929
- const [maxBadge, setMaxBadge] = (0, import_react9.useState)(null);
8930
- const [activeCommands, setActiveCommands] = (0, import_react9.useState)(/* @__PURE__ */ new Set());
8931
- const [sectionGap, setSectionGap] = (0, import_react9.useState)(null);
8932
- const [toolbarShowEditLink, setToolbarShowEditLink] = (0, import_react9.useState)(false);
8933
- const hoveredNavContainerRef = (0, import_react9.useRef)(null);
8934
- const [hoveredNavContainerRect, setHoveredNavContainerRect] = (0, import_react9.useState)(null);
8935
- const hoveredItemElRef = (0, import_react9.useRef)(null);
8936
- const [hoveredItemRect, setHoveredItemRect] = (0, import_react9.useState)(null);
8937
- const siblingHintElRef = (0, import_react9.useRef)(null);
8938
- const [siblingHintRect, setSiblingHintRect] = (0, import_react9.useState)(null);
8939
- const [siblingHintRects, setSiblingHintRects] = (0, import_react9.useState)([]);
8940
- const [isItemDragging, setIsItemDragging] = (0, import_react9.useState)(false);
8941
- const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react9.useState)(false);
8942
- const footerDragRef = (0, import_react9.useRef)(null);
8943
- const [footerDropSlots, setFooterDropSlots] = (0, import_react9.useState)([]);
8944
- const [activeFooterDropIndex, setActiveFooterDropIndex] = (0, import_react9.useState)(null);
8945
- const [draggedItemRect, setDraggedItemRect] = (0, import_react9.useState)(null);
8946
- const footerPointerDragRef = (0, import_react9.useRef)(null);
8947
- const suppressNextClickRef = (0, import_react9.useRef)(false);
8948
- const suppressClickUntilRef = (0, import_react9.useRef)(0);
8949
- const [linkPopover, setLinkPopover] = (0, import_react9.useState)(null);
8950
- const linkPopoverSessionRef = (0, import_react9.useRef)(null);
8951
- const addNavAfterAnchorRef = (0, import_react9.useRef)(null);
8952
- const editContentRef = (0, import_react9.useRef)({});
8953
- const [sitePages, setSitePages] = (0, import_react9.useState)([]);
8954
- const [sectionsByPath, setSectionsByPath] = (0, import_react9.useState)({});
8955
- const sectionsPrefetchGenRef = (0, import_react9.useRef)(0);
8956
- const setLinkPopoverRef = (0, import_react9.useRef)(setLinkPopover);
8957
- const linkPopoverPanelRef = (0, import_react9.useRef)(null);
8958
- const linkPopoverOpenRef = (0, import_react9.useRef)(false);
8959
- const linkPopoverGraceUntilRef = (0, import_react9.useRef)(0);
9185
+ const [selectedIsCta, setSelectedIsCta] = (0, import_react10.useState)(false);
9186
+ const [reorderHrefKey, setReorderHrefKey] = (0, import_react10.useState)(null);
9187
+ const [reorderDragDisabled, setReorderDragDisabled] = (0, import_react10.useState)(false);
9188
+ const [toggleState, setToggleState] = (0, import_react10.useState)(null);
9189
+ const [maxBadge, setMaxBadge] = (0, import_react10.useState)(null);
9190
+ const [activeCommands, setActiveCommands] = (0, import_react10.useState)(/* @__PURE__ */ new Set());
9191
+ const [sectionGap, setSectionGap] = (0, import_react10.useState)(null);
9192
+ const [toolbarShowEditLink, setToolbarShowEditLink] = (0, import_react10.useState)(false);
9193
+ const hoveredNavContainerRef = (0, import_react10.useRef)(null);
9194
+ const [hoveredNavContainerRect, setHoveredNavContainerRect] = (0, import_react10.useState)(null);
9195
+ const hoveredItemElRef = (0, import_react10.useRef)(null);
9196
+ const [hoveredItemRect, setHoveredItemRect] = (0, import_react10.useState)(null);
9197
+ const siblingHintElRef = (0, import_react10.useRef)(null);
9198
+ const [siblingHintRect, setSiblingHintRect] = (0, import_react10.useState)(null);
9199
+ const [siblingHintRects, setSiblingHintRects] = (0, import_react10.useState)([]);
9200
+ const [isItemDragging, setIsItemDragging] = (0, import_react10.useState)(false);
9201
+ const [isFooterFrameSelection, setIsFooterFrameSelection] = (0, import_react10.useState)(false);
9202
+ const footerDragRef = (0, import_react10.useRef)(null);
9203
+ const [footerDropSlots, setFooterDropSlots] = (0, import_react10.useState)([]);
9204
+ const [activeFooterDropIndex, setActiveFooterDropIndex] = (0, import_react10.useState)(null);
9205
+ const [draggedItemRect, setDraggedItemRect] = (0, import_react10.useState)(null);
9206
+ const footerPointerDragRef = (0, import_react10.useRef)(null);
9207
+ const suppressNextClickRef = (0, import_react10.useRef)(false);
9208
+ const suppressClickUntilRef = (0, import_react10.useRef)(0);
9209
+ const [linkPopover, setLinkPopover] = (0, import_react10.useState)(null);
9210
+ const linkPopoverSessionRef = (0, import_react10.useRef)(null);
9211
+ const addNavAfterAnchorRef = (0, import_react10.useRef)(null);
9212
+ const editContentRef = (0, import_react10.useRef)({});
9213
+ const [sitePages, setSitePages] = (0, import_react10.useState)([]);
9214
+ const [sectionsByPath, setSectionsByPath] = (0, import_react10.useState)({});
9215
+ const sectionsPrefetchGenRef = (0, import_react10.useRef)(0);
9216
+ const setLinkPopoverRef = (0, import_react10.useRef)(setLinkPopover);
9217
+ const linkPopoverPanelRef = (0, import_react10.useRef)(null);
9218
+ const linkPopoverOpenRef = (0, import_react10.useRef)(false);
9219
+ const linkPopoverGraceUntilRef = (0, import_react10.useRef)(0);
8960
9220
  setLinkPopoverRef.current = setLinkPopover;
8961
9221
  linkPopoverSessionRef.current = linkPopover;
8962
9222
  const {
@@ -8995,7 +9255,7 @@ function OhhwellsBridge() {
8995
9255
  const bumpLinkPopoverGrace = () => {
8996
9256
  linkPopoverGraceUntilRef.current = Date.now() + 350;
8997
9257
  };
8998
- const runSectionsPrefetch = (0, import_react9.useCallback)((pages) => {
9258
+ const runSectionsPrefetch = (0, import_react10.useCallback)((pages) => {
8999
9259
  if (!isEditMode || shouldUseDevFixtures() || pages.length === 0) return;
9000
9260
  const gen = ++sectionsPrefetchGenRef.current;
9001
9261
  const paths = pages.map((p) => p.path);
@@ -9014,9 +9274,9 @@ function OhhwellsBridge() {
9014
9274
  );
9015
9275
  });
9016
9276
  }, [isEditMode, pathname]);
9017
- const runSectionsPrefetchRef = (0, import_react9.useRef)(runSectionsPrefetch);
9277
+ const runSectionsPrefetchRef = (0, import_react10.useRef)(runSectionsPrefetch);
9018
9278
  runSectionsPrefetchRef.current = runSectionsPrefetch;
9019
- (0, import_react9.useEffect)(() => {
9279
+ (0, import_react10.useEffect)(() => {
9020
9280
  if (!linkPopover) {
9021
9281
  document.documentElement.removeAttribute("data-ohw-link-popover-open");
9022
9282
  return;
@@ -9066,7 +9326,7 @@ function OhhwellsBridge() {
9066
9326
  document.removeEventListener("touchmove", preventBackgroundScroll, scrollOpts);
9067
9327
  };
9068
9328
  }, [linkPopover, postToParent2]);
9069
- (0, import_react9.useEffect)(() => {
9329
+ (0, import_react10.useEffect)(() => {
9070
9330
  if (!isEditMode) return;
9071
9331
  const useFixtures = shouldUseDevFixtures();
9072
9332
  if (useFixtures) {
@@ -9090,14 +9350,14 @@ function OhhwellsBridge() {
9090
9350
  if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
9091
9351
  return () => window.removeEventListener("message", onSitePages);
9092
9352
  }, [isEditMode, postToParent2]);
9093
- (0, import_react9.useEffect)(() => {
9353
+ (0, import_react10.useEffect)(() => {
9094
9354
  if (!isEditMode || shouldUseDevFixtures()) return;
9095
9355
  void loadAllSectionsManifest().then((manifest) => {
9096
9356
  if (Object.keys(manifest).length === 0) return;
9097
9357
  setSectionsByPath((prev) => ({ ...manifest, ...prev }));
9098
9358
  });
9099
9359
  }, [isEditMode]);
9100
- (0, import_react9.useEffect)(() => {
9360
+ (0, import_react10.useEffect)(() => {
9101
9361
  const update = () => {
9102
9362
  const el = activeElRef.current ?? selectedElRef.current;
9103
9363
  if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
@@ -9121,10 +9381,10 @@ function OhhwellsBridge() {
9121
9381
  vvp.removeEventListener("resize", update);
9122
9382
  };
9123
9383
  }, []);
9124
- const refreshStateRules = (0, import_react9.useCallback)(() => {
9384
+ const refreshStateRules = (0, import_react10.useCallback)(() => {
9125
9385
  editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
9126
9386
  }, []);
9127
- const processConfigRequest = (0, import_react9.useCallback)((insertAfterVal) => {
9387
+ const processConfigRequest = (0, import_react10.useCallback)((insertAfterVal) => {
9128
9388
  const tracker = getSectionsTracker();
9129
9389
  let entries = [];
9130
9390
  try {
@@ -9147,7 +9407,7 @@ function OhhwellsBridge() {
9147
9407
  }
9148
9408
  window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: null }, "*");
9149
9409
  }, [isEditMode]);
9150
- const deactivate = (0, import_react9.useCallback)(() => {
9410
+ const deactivate = (0, import_react10.useCallback)(() => {
9151
9411
  const el = activeElRef.current;
9152
9412
  if (!el) return;
9153
9413
  const key = el.dataset.ohwKey;
@@ -9179,12 +9439,12 @@ function OhhwellsBridge() {
9179
9439
  setToolbarShowEditLink(false);
9180
9440
  postToParent2({ type: "ow:exit-edit" });
9181
9441
  }, [postToParent2]);
9182
- const clearSelectedAttr = (0, import_react9.useCallback)(() => {
9442
+ const clearSelectedAttr = (0, import_react10.useCallback)(() => {
9183
9443
  document.querySelectorAll("[data-ohw-selected]").forEach((el) => {
9184
9444
  el.removeAttribute("data-ohw-selected");
9185
9445
  });
9186
9446
  }, []);
9187
- const deselect = (0, import_react9.useCallback)(() => {
9447
+ const deselect = (0, import_react10.useCallback)(() => {
9188
9448
  clearSelectedAttr();
9189
9449
  selectedElRef.current = null;
9190
9450
  selectedHrefKeyRef.current = null;
@@ -9204,11 +9464,11 @@ function OhhwellsBridge() {
9204
9464
  setToolbarVariant("none");
9205
9465
  }
9206
9466
  }, [clearSelectedAttr]);
9207
- const markSelected = (0, import_react9.useCallback)((el) => {
9467
+ const markSelected = (0, import_react10.useCallback)((el) => {
9208
9468
  clearSelectedAttr();
9209
9469
  el.setAttribute("data-ohw-selected", "");
9210
9470
  }, [clearSelectedAttr]);
9211
- const resolveHrefKeyElement = (0, import_react9.useCallback)((hrefKey) => {
9471
+ const resolveHrefKeyElement = (0, import_react10.useCallback)((hrefKey) => {
9212
9472
  if (isFooterHrefKey(hrefKey)) {
9213
9473
  return document.querySelector(
9214
9474
  `footer [data-ohw-href-key="${CSS.escape(hrefKey)}"]`
@@ -9223,7 +9483,7 @@ function OhhwellsBridge() {
9223
9483
  `[data-ohw-href-key="${CSS.escape(hrefKey)}"]`
9224
9484
  );
9225
9485
  }, []);
9226
- const resyncSelectedNavigationItem = (0, import_react9.useCallback)(() => {
9486
+ const resyncSelectedNavigationItem = (0, import_react10.useCallback)(() => {
9227
9487
  const hrefKey = selectedHrefKeyRef.current;
9228
9488
  if (hrefKey) {
9229
9489
  const link = resolveHrefKeyElement(hrefKey);
@@ -9251,7 +9511,7 @@ function OhhwellsBridge() {
9251
9511
  );
9252
9512
  }
9253
9513
  }, [resolveHrefKeyElement]);
9254
- const reselectNavigationItem = (0, import_react9.useCallback)((navAnchor) => {
9514
+ const reselectNavigationItem = (0, import_react10.useCallback)((navAnchor) => {
9255
9515
  selectedElRef.current = navAnchor;
9256
9516
  selectedHrefKeyRef.current = navAnchor.getAttribute("data-ohw-href-key");
9257
9517
  selectedFooterColAttrRef.current = null;
@@ -9266,7 +9526,7 @@ function OhhwellsBridge() {
9266
9526
  setToolbarShowEditLink(false);
9267
9527
  setActiveCommands(/* @__PURE__ */ new Set());
9268
9528
  }, [markSelected]);
9269
- const commitNavigationTextEdit = (0, import_react9.useCallback)((navAnchor) => {
9529
+ const commitNavigationTextEdit = (0, import_react10.useCallback)((navAnchor) => {
9270
9530
  const el = activeElRef.current;
9271
9531
  if (!el) return;
9272
9532
  const key = el.dataset.ohwKey;
@@ -9293,7 +9553,7 @@ function OhhwellsBridge() {
9293
9553
  postToParent2({ type: "ow:exit-edit" });
9294
9554
  reselectNavigationItem(navAnchor);
9295
9555
  }, [postToParent2, reselectNavigationItem]);
9296
- const handleAddTopLevelNavItem = (0, import_react9.useCallback)(() => {
9556
+ const handleAddTopLevelNavItem = (0, import_react10.useCallback)(() => {
9297
9557
  const items = listNavbarItems();
9298
9558
  addNavAfterAnchorRef.current = items[items.length - 1] ?? null;
9299
9559
  deselectRef.current();
@@ -9305,7 +9565,7 @@ function OhhwellsBridge() {
9305
9565
  intent: "add-nav"
9306
9566
  });
9307
9567
  }, []);
9308
- const clearFooterDragVisuals = (0, import_react9.useCallback)(() => {
9568
+ const clearFooterDragVisuals = (0, import_react10.useCallback)(() => {
9309
9569
  footerDragRef.current = null;
9310
9570
  setSiblingHintRects([]);
9311
9571
  setFooterDropSlots([]);
@@ -9314,7 +9574,7 @@ function OhhwellsBridge() {
9314
9574
  setIsItemDragging(false);
9315
9575
  unlockFooterDragInteraction();
9316
9576
  }, []);
9317
- const refreshFooterDragVisuals = (0, import_react9.useCallback)((session, activeSlot, clientX, clientY) => {
9577
+ const refreshFooterDragVisuals = (0, import_react10.useCallback)((session, activeSlot, clientX, clientY) => {
9318
9578
  const dragged = session.draggedEl;
9319
9579
  setDraggedItemRect(dragged.getBoundingClientRect());
9320
9580
  if (typeof clientX === "number" && typeof clientY === "number") {
@@ -9339,13 +9599,13 @@ function OhhwellsBridge() {
9339
9599
  const activeIdx = activeSlot ? slots.findIndex((s) => s.insertIndex === activeSlot.insertIndex) : -1;
9340
9600
  setActiveFooterDropIndex(activeIdx >= 0 ? activeIdx : null);
9341
9601
  }, []);
9342
- const refreshFooterDragVisualsRef = (0, import_react9.useRef)(refreshFooterDragVisuals);
9602
+ const refreshFooterDragVisualsRef = (0, import_react10.useRef)(refreshFooterDragVisuals);
9343
9603
  refreshFooterDragVisualsRef.current = refreshFooterDragVisuals;
9344
- const commitFooterDragRef = (0, import_react9.useRef)(() => {
9604
+ const commitFooterDragRef = (0, import_react10.useRef)(() => {
9345
9605
  });
9346
- const beginFooterDragRef = (0, import_react9.useRef)(() => {
9606
+ const beginFooterDragRef = (0, import_react10.useRef)(() => {
9347
9607
  });
9348
- const beginFooterDrag = (0, import_react9.useCallback)(
9608
+ const beginFooterDrag = (0, import_react10.useCallback)(
9349
9609
  (session) => {
9350
9610
  const rect = session.draggedEl.getBoundingClientRect();
9351
9611
  session.lastClientX = session.lastClientX || rect.left + rect.width / 2;
@@ -9365,7 +9625,7 @@ function OhhwellsBridge() {
9365
9625
  [refreshFooterDragVisuals]
9366
9626
  );
9367
9627
  beginFooterDragRef.current = beginFooterDrag;
9368
- const commitFooterDrag = (0, import_react9.useCallback)(
9628
+ const commitFooterDrag = (0, import_react10.useCallback)(
9369
9629
  (clientX, clientY) => {
9370
9630
  const session = footerDragRef.current;
9371
9631
  if (!session) {
@@ -9469,7 +9729,7 @@ function OhhwellsBridge() {
9469
9729
  [clearFooterDragVisuals, resolveHrefKeyElement, resyncSelectedNavigationItem]
9470
9730
  );
9471
9731
  commitFooterDragRef.current = commitFooterDrag;
9472
- const startFooterLinkDrag = (0, import_react9.useCallback)(
9732
+ const startFooterLinkDrag = (0, import_react10.useCallback)(
9473
9733
  (anchor, clientX, clientY, wasSelected) => {
9474
9734
  const hrefKey = anchor.getAttribute("data-ohw-href-key");
9475
9735
  if (!hrefKey || !isFooterHrefKey(hrefKey)) return false;
@@ -9490,7 +9750,7 @@ function OhhwellsBridge() {
9490
9750
  },
9491
9751
  [beginFooterDrag]
9492
9752
  );
9493
- const startFooterColumnDrag = (0, import_react9.useCallback)(
9753
+ const startFooterColumnDrag = (0, import_react10.useCallback)(
9494
9754
  (columnEl, clientX, clientY, wasSelected) => {
9495
9755
  const columns = listFooterColumns();
9496
9756
  const idx = columns.indexOf(columnEl);
@@ -9510,7 +9770,7 @@ function OhhwellsBridge() {
9510
9770
  },
9511
9771
  [beginFooterDrag]
9512
9772
  );
9513
- const handleItemDragStart = (0, import_react9.useCallback)(
9773
+ const handleItemDragStart = (0, import_react10.useCallback)(
9514
9774
  (e) => {
9515
9775
  const selected = selectedElRef.current;
9516
9776
  if (!selected) {
@@ -9530,7 +9790,7 @@ function OhhwellsBridge() {
9530
9790
  },
9531
9791
  [startFooterColumnDrag, startFooterLinkDrag, startNavLinkDrag]
9532
9792
  );
9533
- const handleItemDragEnd = (0, import_react9.useCallback)(
9793
+ const handleItemDragEnd = (0, import_react10.useCallback)(
9534
9794
  (e) => {
9535
9795
  if (footerDragRef.current) {
9536
9796
  const x = e?.clientX;
@@ -9556,11 +9816,10 @@ function OhhwellsBridge() {
9556
9816
  },
9557
9817
  [commitFooterDrag, commitNavDrag, navDragRef]
9558
9818
  );
9559
- const handleItemChromePointerDown = (0, import_react9.useCallback)((e) => {
9819
+ const handleItemChromePointerDown = (0, import_react10.useCallback)((e) => {
9560
9820
  if (e.button !== 0) return;
9561
9821
  const selected = selectedElRef.current;
9562
9822
  if (!selected) return;
9563
- armFooterPressDrag();
9564
9823
  const hrefKey = selected.getAttribute("data-ohw-href-key");
9565
9824
  if (hrefKey && isFooterHrefKey(hrefKey)) {
9566
9825
  footerPointerDragRef.current = {
@@ -9588,7 +9847,7 @@ function OhhwellsBridge() {
9588
9847
  }
9589
9848
  if (armNavPressFromChrome(selected, e.clientX, e.clientY, e.pointerId)) return;
9590
9849
  }, [armNavPressFromChrome]);
9591
- const handleItemChromeClick = (0, import_react9.useCallback)((clientX, clientY) => {
9850
+ const handleItemChromeClick = (0, import_react10.useCallback)((clientX, clientY) => {
9592
9851
  if (suppressNextClickRef.current || Date.now() < suppressClickUntilRef.current) {
9593
9852
  suppressNextClickRef.current = false;
9594
9853
  return;
@@ -9601,7 +9860,7 @@ function OhhwellsBridge() {
9601
9860
  }, []);
9602
9861
  reselectNavigationItemRef.current = reselectNavigationItem;
9603
9862
  commitNavigationTextEditRef.current = commitNavigationTextEdit;
9604
- const select = (0, import_react9.useCallback)((anchor) => {
9863
+ const select = (0, import_react10.useCallback)((anchor) => {
9605
9864
  if (!isNavigationItem(anchor)) return;
9606
9865
  if (activeElRef.current) deactivate();
9607
9866
  selectedElRef.current = anchor;
@@ -9627,7 +9886,7 @@ function OhhwellsBridge() {
9627
9886
  setToolbarShowEditLink(false);
9628
9887
  setActiveCommands(/* @__PURE__ */ new Set());
9629
9888
  }, [deactivate, markSelected]);
9630
- const selectFrame = (0, import_react9.useCallback)((el) => {
9889
+ const selectFrame = (0, import_react10.useCallback)((el) => {
9631
9890
  if (!isNavigationContainer(el)) return;
9632
9891
  if (activeElRef.current) deactivate();
9633
9892
  const isFooterColumn = el.hasAttribute("data-ohw-footer-col") || Boolean(el.closest("footer") && isInferredFooterGroup(el));
@@ -9655,7 +9914,7 @@ function OhhwellsBridge() {
9655
9914
  setToolbarShowEditLink(false);
9656
9915
  setActiveCommands(/* @__PURE__ */ new Set());
9657
9916
  }, [deactivate, markSelected]);
9658
- const activate = (0, import_react9.useCallback)((el, options) => {
9917
+ const activate = (0, import_react10.useCallback)((el, options) => {
9659
9918
  if (activeElRef.current === el) return;
9660
9919
  clearSelectedAttr();
9661
9920
  selectedElRef.current = null;
@@ -9672,6 +9931,8 @@ function OhhwellsBridge() {
9672
9931
  setSiblingHintRect(null);
9673
9932
  setSiblingHintRects([]);
9674
9933
  setIsItemDragging(false);
9934
+ const preActivationSelection = window.getSelection();
9935
+ const preservedRange = preActivationSelection && preActivationSelection.rangeCount > 0 && !preActivationSelection.isCollapsed && el.contains(preActivationSelection.getRangeAt(0).commonAncestorContainer) ? preActivationSelection.getRangeAt(0).cloneRange() : null;
9675
9936
  el.setAttribute("contenteditable", "true");
9676
9937
  el.setAttribute("data-ohw-editing", "");
9677
9938
  el.removeAttribute("data-ohw-hovered");
@@ -9679,7 +9940,11 @@ function OhhwellsBridge() {
9679
9940
  activeElRef.current = el;
9680
9941
  originalContentRef.current = el.innerHTML;
9681
9942
  el.focus({ preventScroll: true });
9682
- if (options?.caretX !== void 0 && options?.caretY !== void 0) {
9943
+ if (preservedRange) {
9944
+ const selection = window.getSelection();
9945
+ selection?.removeAllRanges();
9946
+ selection?.addRange(preservedRange);
9947
+ } else if (options?.caretX !== void 0 && options?.caretY !== void 0) {
9683
9948
  const { caretX, caretY } = options;
9684
9949
  placeCaretAtPoint(el, caretX, caretY);
9685
9950
  requestAnimationFrame(() => {
@@ -9714,7 +9979,7 @@ function OhhwellsBridge() {
9714
9979
  selectRef.current = select;
9715
9980
  selectFrameRef.current = selectFrame;
9716
9981
  deselectRef.current = deselect;
9717
- (0, import_react9.useLayoutEffect)(() => {
9982
+ (0, import_react10.useLayoutEffect)(() => {
9718
9983
  if (!subdomain || isEditMode) {
9719
9984
  setFetchState("done");
9720
9985
  return;
@@ -9724,6 +9989,7 @@ function OhhwellsBridge() {
9724
9989
  for (const [key, val] of Object.entries(content)) {
9725
9990
  if (key === "__ohw_sections") continue;
9726
9991
  if (applyVideoSettingNode(key, val)) continue;
9992
+ if (applyCarouselNode(key, val)) continue;
9727
9993
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
9728
9994
  if (el.dataset.ohwEditable === "image") {
9729
9995
  const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
@@ -9784,7 +10050,7 @@ function OhhwellsBridge() {
9784
10050
  cancelled = true;
9785
10051
  };
9786
10052
  }, [subdomain, isEditMode]);
9787
- (0, import_react9.useEffect)(() => {
10053
+ (0, import_react10.useEffect)(() => {
9788
10054
  if (!subdomain || isEditMode) return;
9789
10055
  let debounceTimer = null;
9790
10056
  let observer = null;
@@ -9797,6 +10063,7 @@ function OhhwellsBridge() {
9797
10063
  for (const [key, val] of Object.entries(content)) {
9798
10064
  if (key === "__ohw_sections") continue;
9799
10065
  if (applyVideoSettingNode(key, val)) continue;
10066
+ if (applyCarouselNode(key, val)) continue;
9800
10067
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
9801
10068
  if (el.dataset.ohwEditable === "image") {
9802
10069
  const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
@@ -9834,16 +10101,16 @@ function OhhwellsBridge() {
9834
10101
  if (debounceTimer) clearTimeout(debounceTimer);
9835
10102
  };
9836
10103
  }, [subdomain, isEditMode, pathname]);
9837
- (0, import_react9.useLayoutEffect)(() => {
10104
+ (0, import_react10.useLayoutEffect)(() => {
9838
10105
  const el = document.getElementById("ohw-loader");
9839
10106
  if (!el) return;
9840
10107
  const visible = Boolean(subdomain) && fetchState !== "done";
9841
10108
  el.style.display = visible ? "flex" : "none";
9842
10109
  }, [subdomain, fetchState]);
9843
- (0, import_react9.useEffect)(() => {
10110
+ (0, import_react10.useEffect)(() => {
9844
10111
  postToParent2({ type: "ow:navigation", path: pathname });
9845
10112
  }, [pathname, postToParent2]);
9846
- (0, import_react9.useEffect)(() => {
10113
+ (0, import_react10.useEffect)(() => {
9847
10114
  if (!isEditMode) return;
9848
10115
  if (linkPopoverSessionRef.current?.intent === "add-nav") return;
9849
10116
  if (document.querySelector("[data-ohw-section-picker]")) return;
@@ -9851,7 +10118,7 @@ function OhhwellsBridge() {
9851
10118
  deselectRef.current();
9852
10119
  deactivateRef.current();
9853
10120
  }, [pathname, isEditMode]);
9854
- (0, import_react9.useEffect)(() => {
10121
+ (0, import_react10.useEffect)(() => {
9855
10122
  const contentForNav = () => {
9856
10123
  if (isEditMode) return editContentRef.current;
9857
10124
  if (!subdomain) return {};
@@ -9916,7 +10183,7 @@ function OhhwellsBridge() {
9916
10183
  observer?.disconnect();
9917
10184
  };
9918
10185
  }, [isEditMode, pathname, subdomain, fetchState, resyncSelectedNavigationItem]);
9919
- (0, import_react9.useEffect)(() => {
10186
+ (0, import_react10.useEffect)(() => {
9920
10187
  if (!isEditMode) return;
9921
10188
  const measure = () => {
9922
10189
  const h = document.body.scrollHeight;
@@ -9940,7 +10207,7 @@ function OhhwellsBridge() {
9940
10207
  window.removeEventListener("resize", handleResize);
9941
10208
  };
9942
10209
  }, [pathname, isEditMode, postToParent2]);
9943
- (0, import_react9.useEffect)(() => {
10210
+ (0, import_react10.useEffect)(() => {
9944
10211
  if (!subdomainFromQuery || isEditMode) return;
9945
10212
  const handleClick = (e) => {
9946
10213
  const anchor = e.target.closest("a");
@@ -9956,7 +10223,7 @@ function OhhwellsBridge() {
9956
10223
  document.addEventListener("click", handleClick, true);
9957
10224
  return () => document.removeEventListener("click", handleClick, true);
9958
10225
  }, [subdomainFromQuery, isEditMode, router]);
9959
- (0, import_react9.useEffect)(() => {
10226
+ (0, import_react10.useEffect)(() => {
9960
10227
  if (!isEditMode) {
9961
10228
  editStylesRef.current?.base.remove();
9962
10229
  editStylesRef.current?.forceHover.remove();
@@ -10135,7 +10402,9 @@ function OhhwellsBridge() {
10135
10402
  if (inActive || inActiveNav) {
10136
10403
  e.preventDefault();
10137
10404
  e.stopPropagation();
10138
- if (e.detail < 2) {
10405
+ const selection = window.getSelection();
10406
+ const hasRangeSelection = Boolean(selection && !selection.isCollapsed);
10407
+ if (e.detail < 2 && !hasRangeSelection) {
10139
10408
  placeCaretAtPoint(active, e.clientX, e.clientY);
10140
10409
  refreshActiveCommandsRef.current();
10141
10410
  }
@@ -11019,6 +11288,7 @@ function OhhwellsBridge() {
11019
11288
  continue;
11020
11289
  }
11021
11290
  if (applyVideoSettingNode(key, val)) continue;
11291
+ if (applyCarouselNode(key, val)) continue;
11022
11292
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
11023
11293
  if (el.dataset.ohwEditable === "image") {
11024
11294
  const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
@@ -11288,33 +11558,34 @@ function OhhwellsBridge() {
11288
11558
  const h = document.documentElement.scrollHeight;
11289
11559
  if (h > 50) postToParentRef.current({ type: "ow:height", height: h });
11290
11560
  };
11561
+ let selectionChangeRaf = null;
11562
+ const runSelectionChange = () => {
11563
+ selectionChangeRaf = null;
11564
+ const activeRoot = activeElRef.current;
11565
+ if (!activeRoot) return;
11566
+ const startEl = resolveSelectionStartElement(window.getSelection());
11567
+ const next = startEl ? detectActiveFormats(startEl, activeRoot) : /* @__PURE__ */ new Set();
11568
+ setActiveCommands((prev) => setsEqual(prev, next) ? prev : next);
11569
+ };
11291
11570
  const handleSelectionChange = () => {
11292
- if (!activeElRef.current) return;
11293
- const next = /* @__PURE__ */ new Set();
11294
- for (const cmd of ["bold", "italic", "underline", "strikeThrough", "insertUnorderedList", "insertOrderedList"]) {
11295
- try {
11296
- if (document.queryCommandState(cmd)) next.add(cmd);
11297
- } catch {
11298
- }
11299
- }
11300
- const sel = window.getSelection();
11301
- const anchor = sel?.anchorNode;
11302
- if (anchor) {
11303
- const el = anchor.nodeType === Node.TEXT_NODE ? anchor.parentElement : anchor;
11304
- const block = el?.closest("div, p, h1, h2, h3, h4, h5, h6, li, td, th") ?? el;
11305
- if (block) {
11306
- const align = getComputedStyle(block).textAlign;
11307
- if (align === "center") next.add("justifyCenter");
11308
- else if (align === "right" || align === "end") next.add("justifyRight");
11309
- else next.add("justifyLeft");
11310
- }
11311
- }
11312
- setActiveCommands(next);
11571
+ if (pointerHeldRef.current) return;
11572
+ if (selectionChangeRaf !== null) return;
11573
+ selectionChangeRaf = requestAnimationFrame(runSelectionChange);
11574
+ };
11575
+ const markPointerHeld = (e) => {
11576
+ if (e.button !== 0) return;
11577
+ pointerHeldRef.current = true;
11578
+ };
11579
+ const markPointerReleased = () => {
11580
+ if (!pointerHeldRef.current) return;
11581
+ pointerHeldRef.current = false;
11582
+ handleSelectionChange();
11313
11583
  };
11314
- refreshActiveCommandsRef.current = handleSelectionChange;
11584
+ refreshActiveCommandsRef.current = runSelectionChange;
11315
11585
  const handleDocMouseLeave = () => {
11316
11586
  hoveredImageRef.current = null;
11317
11587
  setMediaHover(null);
11588
+ setCarouselHover(null);
11318
11589
  document.querySelectorAll("[data-ohw-state-hovered]").forEach((el) => el.removeAttribute("data-ohw-state-hovered"));
11319
11590
  document.querySelectorAll("[data-ohw-hovered]").forEach((el) => el.removeAttribute("data-ohw-hovered"));
11320
11591
  activeStateElRef.current = null;
@@ -11354,6 +11625,48 @@ function OhhwellsBridge() {
11354
11625
  if (e.data?.type !== "ow:canvas-height" || typeof e.data.height !== "number") return;
11355
11626
  document.documentElement.style.setProperty("--ohw-canvas-h", `${e.data.height}px`);
11356
11627
  };
11628
+ const handleCarouselChange = (e) => {
11629
+ if (e.data?.type !== "ow:carousel-change") return;
11630
+ const { key, images } = e.data;
11631
+ if (!key || !Array.isArray(images)) return;
11632
+ const text = JSON.stringify(images);
11633
+ applyCarouselValue(key, images);
11634
+ editContentRef.current = { ...editContentRef.current, [key]: text };
11635
+ postToParentRef.current({ type: "ow:change", nodes: [{ key, text }] });
11636
+ setCarouselHover(null);
11637
+ };
11638
+ const findCarouselAtPoint = (clientX, clientY) => {
11639
+ const containers = Array.from(document.querySelectorAll(`[${CAROUSEL_ATTR}]`));
11640
+ for (let i = containers.length - 1; i >= 0; i--) {
11641
+ const r2 = containers[i].getBoundingClientRect();
11642
+ if (clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom) {
11643
+ return containers[i];
11644
+ }
11645
+ }
11646
+ return null;
11647
+ };
11648
+ const isPointOverEditable = (scope, clientX, clientY) => {
11649
+ const editables = scope.querySelectorAll("[data-ohw-editable], [data-ohw-href-key]");
11650
+ for (const el of editables) {
11651
+ const r2 = el.getBoundingClientRect();
11652
+ if (clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom) return true;
11653
+ }
11654
+ return false;
11655
+ };
11656
+ const handleCarouselHover = (e) => {
11657
+ const container = findCarouselAtPoint(e.clientX, e.clientY);
11658
+ const scope = container?.closest("[data-ohw-section]") ?? container?.parentElement ?? null;
11659
+ if (!container || !scope || isPointOverEditable(scope, e.clientX, e.clientY)) {
11660
+ setCarouselHover((prev) => prev ? null : prev);
11661
+ return;
11662
+ }
11663
+ const key = container.getAttribute("data-ohw-key") ?? "";
11664
+ if (!key) return;
11665
+ const r2 = getVisibleRect(container);
11666
+ setCarouselHover(
11667
+ (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 } }
11668
+ );
11669
+ };
11357
11670
  const applyToolbarPos = (rect) => {
11358
11671
  const ps = parentScrollRef.current;
11359
11672
  const measuredW = toolbarElRef.current?.offsetWidth || 330;
@@ -11467,6 +11780,7 @@ function OhhwellsBridge() {
11467
11780
  window.addEventListener("message", handleRemoveSchedulingSection);
11468
11781
  window.addEventListener("message", handleImageUrl);
11469
11782
  window.addEventListener("message", handleImageUploading);
11783
+ window.addEventListener("message", handleCarouselChange);
11470
11784
  window.addEventListener("message", handleCanvasHeight);
11471
11785
  window.addEventListener("message", handleParentScroll);
11472
11786
  window.addEventListener("message", handlePointerSync);
@@ -11484,6 +11798,7 @@ function OhhwellsBridge() {
11484
11798
  document.addEventListener("mouseover", handleMouseOver, true);
11485
11799
  document.addEventListener("mouseout", handleMouseOut, true);
11486
11800
  document.addEventListener("mousemove", handleMouseMove, true);
11801
+ document.addEventListener("mousemove", handleCarouselHover, true);
11487
11802
  document.addEventListener("mouseleave", handleDocMouseLeave);
11488
11803
  document.addEventListener("dragover", handleDragOver, true);
11489
11804
  document.addEventListener("dragleave", handleDragLeave, true);
@@ -11499,6 +11814,7 @@ function OhhwellsBridge() {
11499
11814
  document.removeEventListener("mouseover", handleMouseOver, true);
11500
11815
  document.removeEventListener("mouseout", handleMouseOut, true);
11501
11816
  document.removeEventListener("mousemove", handleMouseMove, true);
11817
+ document.removeEventListener("mousemove", handleCarouselHover, true);
11502
11818
  document.removeEventListener("mouseleave", handleDocMouseLeave);
11503
11819
  document.removeEventListener("dragover", handleDragOver, true);
11504
11820
  document.removeEventListener("dragleave", handleDragLeave, true);
@@ -11514,6 +11830,7 @@ function OhhwellsBridge() {
11514
11830
  window.removeEventListener("message", handleRemoveSchedulingSection);
11515
11831
  window.removeEventListener("message", handleImageUrl);
11516
11832
  window.removeEventListener("message", handleImageUploading);
11833
+ window.removeEventListener("message", handleCarouselChange);
11517
11834
  window.removeEventListener("message", handleCanvasHeight);
11518
11835
  window.removeEventListener("message", handleParentScroll);
11519
11836
  window.removeEventListener("resize", handleViewportResize);
@@ -11528,7 +11845,7 @@ function OhhwellsBridge() {
11528
11845
  if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
11529
11846
  };
11530
11847
  }, [isEditMode, refreshStateRules]);
11531
- (0, import_react9.useEffect)(() => {
11848
+ (0, import_react10.useEffect)(() => {
11532
11849
  if (!isEditMode) return;
11533
11850
  const THRESHOLD = 10;
11534
11851
  const resolveWasSelected = (el) => {
@@ -11551,7 +11868,6 @@ function OhhwellsBridge() {
11551
11868
  const anchor = getNavigationItemAnchor(target);
11552
11869
  const hrefKey = anchor?.getAttribute("data-ohw-href-key") ?? null;
11553
11870
  if (anchor && isFooterHrefKey(hrefKey)) {
11554
- armFooterPressDrag();
11555
11871
  footerPointerDragRef.current = {
11556
11872
  el: anchor,
11557
11873
  kind: "link",
@@ -11565,7 +11881,6 @@ function OhhwellsBridge() {
11565
11881
  }
11566
11882
  const col = target.closest("[data-ohw-footer-col]");
11567
11883
  if (col && !getNavigationItemAnchor(target)) {
11568
- armFooterPressDrag();
11569
11884
  footerPointerDragRef.current = {
11570
11885
  el: col,
11571
11886
  kind: "column",
@@ -11594,6 +11909,7 @@ function OhhwellsBridge() {
11594
11909
  if (dx * dx + dy * dy < THRESHOLD * THRESHOLD) return;
11595
11910
  e.preventDefault();
11596
11911
  pending.started = true;
11912
+ armFooterPressDrag();
11597
11913
  clearTextSelection();
11598
11914
  try {
11599
11915
  document.body.setPointerCapture(pending.pointerId);
@@ -11647,7 +11963,8 @@ function OhhwellsBridge() {
11647
11963
  }
11648
11964
  } catch {
11649
11965
  }
11650
- if (!pending?.started) {
11966
+ if (!pending) return;
11967
+ if (!pending.started) {
11651
11968
  unlockFooterDragInteraction();
11652
11969
  return;
11653
11970
  }
@@ -11682,7 +11999,7 @@ function OhhwellsBridge() {
11682
11999
  unlockFooterDragInteraction();
11683
12000
  };
11684
12001
  }, [isEditMode]);
11685
- (0, import_react9.useEffect)(() => {
12002
+ (0, import_react10.useEffect)(() => {
11686
12003
  const handler = (e) => {
11687
12004
  if (e.data?.type !== "ow:request-schedule-config") return;
11688
12005
  const insertAfterVal = e.data.insertAfter;
@@ -11698,7 +12015,7 @@ function OhhwellsBridge() {
11698
12015
  window.addEventListener("message", handler);
11699
12016
  return () => window.removeEventListener("message", handler);
11700
12017
  }, [processConfigRequest]);
11701
- (0, import_react9.useEffect)(() => {
12018
+ (0, import_react10.useEffect)(() => {
11702
12019
  if (!isEditMode) return;
11703
12020
  document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {
11704
12021
  el.removeAttribute("data-ohw-active-state");
@@ -11733,19 +12050,49 @@ function OhhwellsBridge() {
11733
12050
  clearTimeout(timer);
11734
12051
  };
11735
12052
  }, [pathname, isEditMode, refreshStateRules, postToParent2]);
11736
- (0, import_react9.useEffect)(() => {
12053
+ (0, import_react10.useEffect)(() => {
11737
12054
  scrollToHashSectionWhenReady();
11738
12055
  const onHashChange = () => scrollToHashSectionWhenReady();
11739
12056
  window.addEventListener("hashchange", onHashChange);
11740
12057
  return () => window.removeEventListener("hashchange", onHashChange);
11741
12058
  }, [pathname]);
11742
- const handleCommand = (0, import_react9.useCallback)((cmd) => {
12059
+ const handleCommand = (0, import_react10.useCallback)((cmd) => {
12060
+ const el = activeElRef.current;
12061
+ const selBefore = window.getSelection();
12062
+ let savedOffsets = null;
12063
+ if (el && selBefore && selBefore.rangeCount > 0 && !selBefore.isCollapsed) {
12064
+ const r2 = selBefore.getRangeAt(0);
12065
+ if (el.contains(r2.commonAncestorContainer)) {
12066
+ savedOffsets = {
12067
+ start: textOffsetInRoot(el, r2.startContainer, r2.startOffset),
12068
+ end: textOffsetInRoot(el, r2.endContainer, r2.endOffset)
12069
+ };
12070
+ }
12071
+ }
12072
+ document.execCommand("styleWithCSS", false, true);
11743
12073
  document.execCommand(cmd, false);
11744
- activeElRef.current?.focus();
11745
- if (activeElRef.current) setToolbarRect(getEditMeasureEl(activeElRef.current).getBoundingClientRect());
12074
+ if (el && document.activeElement !== el) {
12075
+ el.focus();
12076
+ }
12077
+ const selAfter = window.getSelection();
12078
+ if (el && savedOffsets && selAfter?.isCollapsed) {
12079
+ const start = pointAtTextOffset(el, savedOffsets.start);
12080
+ const end = pointAtTextOffset(el, savedOffsets.end);
12081
+ if (start && end) {
12082
+ try {
12083
+ const range = document.createRange();
12084
+ range.setStart(start.node, start.offset);
12085
+ range.setEnd(end.node, end.offset);
12086
+ selAfter.removeAllRanges();
12087
+ selAfter.addRange(range);
12088
+ } catch {
12089
+ }
12090
+ }
12091
+ }
12092
+ if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
11746
12093
  refreshActiveCommandsRef.current();
11747
12094
  }, []);
11748
- const handleStateChange = (0, import_react9.useCallback)((state) => {
12095
+ const handleStateChange = (0, import_react10.useCallback)((state) => {
11749
12096
  if (!activeStateElRef.current) return;
11750
12097
  const el = activeStateElRef.current;
11751
12098
  if (state === "Default") {
@@ -11758,11 +12105,11 @@ function OhhwellsBridge() {
11758
12105
  }
11759
12106
  setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
11760
12107
  }, [deactivate]);
11761
- const closeLinkPopover = (0, import_react9.useCallback)(() => {
12108
+ const closeLinkPopover = (0, import_react10.useCallback)(() => {
11762
12109
  addNavAfterAnchorRef.current = null;
11763
12110
  setLinkPopover(null);
11764
12111
  }, []);
11765
- const openLinkPopoverForActive = (0, import_react9.useCallback)(() => {
12112
+ const openLinkPopoverForActive = (0, import_react10.useCallback)(() => {
11766
12113
  const hrefCtx = getHrefKeyFromElement(activeElRef.current);
11767
12114
  if (!hrefCtx) return;
11768
12115
  bumpLinkPopoverGrace();
@@ -11773,7 +12120,7 @@ function OhhwellsBridge() {
11773
12120
  });
11774
12121
  deactivate();
11775
12122
  }, [deactivate]);
11776
- const openLinkPopoverForSelected = (0, import_react9.useCallback)(() => {
12123
+ const openLinkPopoverForSelected = (0, import_react10.useCallback)(() => {
11777
12124
  const anchor = selectedElRef.current;
11778
12125
  if (!anchor) return;
11779
12126
  const key = anchor.getAttribute("data-ohw-href-key");
@@ -11786,7 +12133,7 @@ function OhhwellsBridge() {
11786
12133
  });
11787
12134
  deselect();
11788
12135
  }, [deselect]);
11789
- const handleLinkPopoverSubmit = (0, import_react9.useCallback)(
12136
+ const handleLinkPopoverSubmit = (0, import_react10.useCallback)(
11790
12137
  (target) => {
11791
12138
  const session = linkPopoverSessionRef.current;
11792
12139
  if (!session) return;
@@ -11845,13 +12192,19 @@ function OhhwellsBridge() {
11845
12192
  const showEditLink = toolbarShowEditLink;
11846
12193
  const currentSections = sectionsByPath[pathname] ?? [];
11847
12194
  linkPopoverOpenRef.current = linkPopover !== null;
11848
- const handleMediaReplace = (0, import_react9.useCallback)(
12195
+ const handleMediaReplace = (0, import_react10.useCallback)(
11849
12196
  (key) => {
11850
12197
  postToParent2({ type: "ow:image-pick", key, elementType: mediaHover?.elementType ?? "image" });
11851
12198
  },
11852
12199
  [postToParent2, mediaHover?.elementType]
11853
12200
  );
11854
- const handleMediaFadeOutComplete = (0, import_react9.useCallback)((key) => {
12201
+ const handleEditCarousel = (0, import_react10.useCallback)(
12202
+ (key) => {
12203
+ postToParent2({ type: "ow:carousel-open", key, images: readCarouselValue(key) });
12204
+ },
12205
+ [postToParent2]
12206
+ );
12207
+ const handleMediaFadeOutComplete = (0, import_react10.useCallback)((key) => {
11855
12208
  setUploadingRects((prev) => {
11856
12209
  if (!(key in prev)) return prev;
11857
12210
  const next = { ...prev };
@@ -11859,7 +12212,7 @@ function OhhwellsBridge() {
11859
12212
  return next;
11860
12213
  });
11861
12214
  }, []);
11862
- const handleVideoSettingsChange = (0, import_react9.useCallback)(
12215
+ const handleVideoSettingsChange = (0, import_react10.useCallback)(
11863
12216
  (key, settings) => {
11864
12217
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
11865
12218
  const video = getVideoEl(el);
@@ -11882,9 +12235,9 @@ function OhhwellsBridge() {
11882
12235
  [postToParent2]
11883
12236
  );
11884
12237
  return bridgeRoot ? (0, import_react_dom3.createPortal)(
11885
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
11886
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
11887
- Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
12238
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
12239
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
12240
+ Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
11888
12241
  MediaOverlay,
11889
12242
  {
11890
12243
  hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
@@ -11895,7 +12248,7 @@ function OhhwellsBridge() {
11895
12248
  },
11896
12249
  `uploading-${key}`
11897
12250
  )),
11898
- mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
12251
+ mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
11899
12252
  MediaOverlay,
11900
12253
  {
11901
12254
  hover: mediaHover,
@@ -11904,10 +12257,11 @@ function OhhwellsBridge() {
11904
12257
  onVideoSettingsChange: handleVideoSettingsChange
11905
12258
  }
11906
12259
  ),
11907
- siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
11908
- siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
11909
- isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
11910
- isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
12260
+ carouselHover && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
12261
+ siblingHintRect && !linkPopover && !isItemDragging && siblingHintRects.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
12262
+ siblingHintRects.length > 0 && !linkPopover && !isItemDragging && siblingHintRects.map((rect, i) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ItemInteractionLayer, { rect, state: "sibling-hint" }, `sibling-hint-${i}`)),
12263
+ isItemDragging && draggedItemRect && selectedElRef.current !== footerDragRef.current?.draggedEl && selectedElRef.current !== navDragRef.current?.draggedEl && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ItemInteractionLayer, { rect: draggedItemRect, state: "dragging" }),
12264
+ isItemDragging && footerDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
11911
12265
  "div",
11912
12266
  {
11913
12267
  className: "pointer-events-none fixed z-2147483646",
@@ -11917,7 +12271,7 @@ function OhhwellsBridge() {
11917
12271
  width: slot.width,
11918
12272
  height: slot.height
11919
12273
  },
11920
- children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
12274
+ children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
11921
12275
  DropIndicator,
11922
12276
  {
11923
12277
  direction: slot.direction,
@@ -11928,7 +12282,7 @@ function OhhwellsBridge() {
11928
12282
  },
11929
12283
  `footer-drop-${slot.direction}-${slot.columnIndex}-${slot.insertIndex}-${i}`
11930
12284
  )),
11931
- isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
12285
+ isItemDragging && navDropSlots.map((slot, i) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
11932
12286
  "div",
11933
12287
  {
11934
12288
  className: "pointer-events-none fixed z-2147483646",
@@ -11938,7 +12292,7 @@ function OhhwellsBridge() {
11938
12292
  width: slot.width,
11939
12293
  height: slot.height
11940
12294
  },
11941
- children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
12295
+ children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
11942
12296
  DropIndicator,
11943
12297
  {
11944
12298
  direction: slot.direction,
@@ -11949,10 +12303,10 @@ function OhhwellsBridge() {
11949
12303
  },
11950
12304
  `nav-drop-${slot.direction}-${slot.parentId ?? "root"}-${slot.insertIndex}-${i}`
11951
12305
  )),
11952
- hoveredNavContainerRect && toolbarVariant !== "select-frame" && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
11953
- hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
11954
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
11955
- toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
12306
+ hoveredNavContainerRect && toolbarVariant !== "select-frame" && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
12307
+ hoveredItemRect && !linkPopover && !hoveredNavContainerRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
12308
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && !isFooterFrameSelection && selectedElRef.current && isNavbarLinksContainer(selectedElRef.current) && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(NavbarContainerChrome, { rect: toolbarRect, onAdd: handleAddTopLevelNavItem }),
12309
+ toolbarRect && !linkPopover && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
11956
12310
  ItemInteractionLayer,
11957
12311
  {
11958
12312
  rect: isItemDragging && draggedItemRect && (footerDragRef.current?.wasSelected || navDragRef.current?.wasSelected) ? draggedItemRect : toolbarRect,
@@ -11966,7 +12320,7 @@ function OhhwellsBridge() {
11966
12320
  onItemPointerDown: handleItemChromePointerDown,
11967
12321
  onItemClick: handleItemChromeClick,
11968
12322
  itemDragSurface: !isFooterFrameSelection,
11969
- toolbar: toolbarVariant === "link-action" && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
12323
+ toolbar: toolbarVariant === "link-action" && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
11970
12324
  ItemActionToolbar,
11971
12325
  {
11972
12326
  onEditLink: openLinkPopoverForSelected,
@@ -11979,8 +12333,8 @@ function OhhwellsBridge() {
11979
12333
  ) : void 0
11980
12334
  }
11981
12335
  ),
11982
- toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
11983
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
12336
+ toolbarRect && toolbarVariant === "rich-text" && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
12337
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
11984
12338
  EditGlowChrome,
11985
12339
  {
11986
12340
  rect: toolbarRect,
@@ -11990,7 +12344,7 @@ function OhhwellsBridge() {
11990
12344
  hideHandle: isItemDragging
11991
12345
  }
11992
12346
  ),
11993
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
12347
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
11994
12348
  FloatingToolbar,
11995
12349
  {
11996
12350
  rect: toolbarRect,
@@ -12003,7 +12357,7 @@ function OhhwellsBridge() {
12003
12357
  }
12004
12358
  )
12005
12359
  ] }),
12006
- maxBadge && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
12360
+ maxBadge && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
12007
12361
  "div",
12008
12362
  {
12009
12363
  "data-ohw-max-badge": "",
@@ -12029,7 +12383,7 @@ function OhhwellsBridge() {
12029
12383
  ]
12030
12384
  }
12031
12385
  ),
12032
- toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
12386
+ toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
12033
12387
  StateToggle,
12034
12388
  {
12035
12389
  rect: toggleState.rect,
@@ -12038,15 +12392,15 @@ function OhhwellsBridge() {
12038
12392
  onStateChange: handleStateChange
12039
12393
  }
12040
12394
  ),
12041
- sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
12395
+ sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
12042
12396
  "div",
12043
12397
  {
12044
12398
  "data-ohw-section-insert-line": "",
12045
12399
  className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
12046
12400
  style: { top: sectionGap.y, transform: "translateY(-50%)" },
12047
12401
  children: [
12048
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
12049
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
12402
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
12403
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
12050
12404
  Badge,
12051
12405
  {
12052
12406
  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",
@@ -12063,11 +12417,11 @@ function OhhwellsBridge() {
12063
12417
  children: "Add Section"
12064
12418
  }
12065
12419
  ),
12066
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
12420
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
12067
12421
  ]
12068
12422
  }
12069
12423
  ),
12070
- linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
12424
+ linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
12071
12425
  LinkPopover,
12072
12426
  {
12073
12427
  panelRef: linkPopoverPanelRef,
@@ -12116,6 +12470,7 @@ function OhhwellsBridge() {
12116
12470
  isValidUrl,
12117
12471
  parseTarget,
12118
12472
  toggleVariants,
12473
+ useOhwCarousel,
12119
12474
  validateUrlInput
12120
12475
  });
12121
12476
  //# sourceMappingURL=index.cjs.map