@ohhwells/bridge 0.1.38-next.57 → 0.1.38-next.59

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
@@ -35,6 +35,7 @@ __export(index_exports, {
35
35
  CustomToolbarButton: () => CustomToolbarButton,
36
36
  CustomToolbarDivider: () => CustomToolbarDivider,
37
37
  DragHandle: () => DragHandle,
38
+ DropIndicator: () => DropIndicator,
38
39
  ItemActionToolbar: () => ItemActionToolbar,
39
40
  ItemInteractionLayer: () => ItemInteractionLayer,
40
41
  LinkEditorPanel: () => LinkEditorPanel,
@@ -49,18 +50,20 @@ __export(index_exports, {
49
50
  TooltipProvider: () => TooltipProvider,
50
51
  TooltipTrigger: () => TooltipTrigger,
51
52
  buildTarget: () => buildTarget,
53
+ dropIndicatorVariants: () => dropIndicatorVariants,
52
54
  filterAvailablePages: () => filterAvailablePages,
53
55
  getEditModeInitialState: () => getEditModeInitialState,
54
56
  isEditSessionActive: () => isEditSessionActive,
55
57
  isValidUrl: () => isValidUrl,
56
58
  parseTarget: () => parseTarget,
57
59
  toggleVariants: () => toggleVariants,
60
+ useOhwCarousel: () => useOhwCarousel,
58
61
  validateUrlInput: () => validateUrlInput
59
62
  });
60
63
  module.exports = __toCommonJS(index_exports);
61
64
 
62
65
  // src/OhhwellsBridge.tsx
63
- var import_react8 = __toESM(require("react"), 1);
66
+ var import_react9 = __toESM(require("react"), 1);
64
67
  var import_client = require("react-dom/client");
65
68
  var import_react_dom2 = require("react-dom");
66
69
 
@@ -4859,6 +4862,61 @@ function MediaOverlay({
4859
4862
  ] });
4860
4863
  }
4861
4864
 
4865
+ // src/ui/CarouselOverlay.tsx
4866
+ var import_lucide_react4 = require("lucide-react");
4867
+ var import_jsx_runtime12 = require("react/jsx-runtime");
4868
+ var OVERLAY_BUTTON_STYLE2 = {
4869
+ pointerEvents: "auto",
4870
+ fontFamily: "Inter, sans-serif",
4871
+ fontSize: 12,
4872
+ color: "#000"
4873
+ };
4874
+ function CarouselOverlay({
4875
+ hover,
4876
+ onEdit
4877
+ }) {
4878
+ const { rect } = hover;
4879
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
4880
+ "div",
4881
+ {
4882
+ "data-ohw-bridge": "",
4883
+ "data-ohw-carousel-overlay": "",
4884
+ className: "flex cursor-pointer items-center justify-center",
4885
+ style: {
4886
+ position: "fixed",
4887
+ top: rect.top,
4888
+ left: rect.left,
4889
+ width: rect.width,
4890
+ height: rect.height,
4891
+ zIndex: 2147483646,
4892
+ pointerEvents: "auto",
4893
+ boxShadow: "inset 0 0 0 1.5px var(--color-primary)",
4894
+ background: "color-mix(in srgb, var(--color-primary) 20%, transparent)"
4895
+ },
4896
+ onClick: () => onEdit(hover.key),
4897
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
4898
+ Button,
4899
+ {
4900
+ "data-ohw-carousel-overlay": "",
4901
+ variant: "outline",
4902
+ size: "sm",
4903
+ className: "cursor-pointer gap-1.5 hover:bg-background",
4904
+ style: OVERLAY_BUTTON_STYLE2,
4905
+ onMouseDown: (e) => e.preventDefault(),
4906
+ onClick: (e) => {
4907
+ e.stopPropagation();
4908
+ onEdit(hover.key);
4909
+ },
4910
+ children: [
4911
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react4.GalleryHorizontal, { size: 14 }),
4912
+ "Edit gallery"
4913
+ ]
4914
+ }
4915
+ )
4916
+ }
4917
+ );
4918
+ }
4919
+
4862
4920
  // src/OhhwellsBridge.tsx
4863
4921
  var import_react_dom3 = require("react-dom");
4864
4922
  var import_navigation2 = require("next/navigation");
@@ -5143,23 +5201,23 @@ var import_react7 = require("react");
5143
5201
  // src/ui/dialog.tsx
5144
5202
  var React7 = __toESM(require("react"), 1);
5145
5203
  var import_radix_ui5 = require("radix-ui");
5146
- var import_lucide_react4 = require("lucide-react");
5147
- var import_jsx_runtime12 = require("react/jsx-runtime");
5204
+ var import_lucide_react5 = require("lucide-react");
5205
+ var import_jsx_runtime13 = require("react/jsx-runtime");
5148
5206
  function Dialog2({
5149
5207
  ...props
5150
5208
  }) {
5151
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_radix_ui5.Dialog.Root, { "data-slot": "dialog", ...props });
5209
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_radix_ui5.Dialog.Root, { "data-slot": "dialog", ...props });
5152
5210
  }
5153
5211
  function DialogPortal({
5154
5212
  ...props
5155
5213
  }) {
5156
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_radix_ui5.Dialog.Portal, { ...props });
5214
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_radix_ui5.Dialog.Portal, { ...props });
5157
5215
  }
5158
5216
  function DialogOverlay({
5159
5217
  className,
5160
5218
  ...props
5161
5219
  }) {
5162
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5220
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5163
5221
  import_radix_ui5.Dialog.Overlay,
5164
5222
  {
5165
5223
  "data-slot": "dialog-overlay",
@@ -5172,9 +5230,9 @@ function DialogOverlay({
5172
5230
  var DialogContent = React7.forwardRef(
5173
5231
  ({ className, children, showCloseButton = true, container, ...props }, ref) => {
5174
5232
  const positionMode = container ? "absolute" : "fixed";
5175
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(DialogPortal, { container: container ?? void 0, children: [
5176
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(DialogOverlay, { className: cn(positionMode, "inset-0") }),
5177
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
5233
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(DialogPortal, { container: container ?? void 0, children: [
5234
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(DialogOverlay, { className: cn(positionMode, "inset-0") }),
5235
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
5178
5236
  import_radix_ui5.Dialog.Content,
5179
5237
  {
5180
5238
  ref,
@@ -5190,13 +5248,13 @@ var DialogContent = React7.forwardRef(
5190
5248
  ...props,
5191
5249
  children: [
5192
5250
  children,
5193
- showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5251
+ showCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5194
5252
  import_radix_ui5.Dialog.Close,
5195
5253
  {
5196
5254
  type: "button",
5197
5255
  className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50",
5198
5256
  "aria-label": "Close",
5199
- children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react4.X, { size: 16, "aria-hidden": true })
5257
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react5.X, { size: 16, "aria-hidden": true })
5200
5258
  }
5201
5259
  ) : null
5202
5260
  ]
@@ -5210,13 +5268,13 @@ function DialogHeader({
5210
5268
  className,
5211
5269
  ...props
5212
5270
  }) {
5213
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: cn("flex flex-col gap-1.5", className), ...props });
5271
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: cn("flex flex-col gap-1.5", className), ...props });
5214
5272
  }
5215
5273
  function DialogFooter({
5216
5274
  className,
5217
5275
  ...props
5218
5276
  }) {
5219
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5277
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5220
5278
  "div",
5221
5279
  {
5222
5280
  className: cn("flex items-center justify-end gap-2", className),
@@ -5224,7 +5282,7 @@ function DialogFooter({
5224
5282
  }
5225
5283
  );
5226
5284
  }
5227
- var DialogTitle = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5285
+ var DialogTitle = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5228
5286
  import_radix_ui5.Dialog.Title,
5229
5287
  {
5230
5288
  ref,
@@ -5236,7 +5294,7 @@ var DialogTitle = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE
5236
5294
  }
5237
5295
  ));
5238
5296
  DialogTitle.displayName = import_radix_ui5.Dialog.Title.displayName;
5239
- var DialogDescription = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5297
+ var DialogDescription = React7.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5240
5298
  import_radix_ui5.Dialog.Description,
5241
5299
  {
5242
5300
  ref,
@@ -5248,63 +5306,63 @@ DialogDescription.displayName = import_radix_ui5.Dialog.Description.displayName;
5248
5306
  var DialogClose = import_radix_ui5.Dialog.Close;
5249
5307
 
5250
5308
  // src/ui/link-modal/LinkEditorPanel.tsx
5251
- var import_lucide_react8 = require("lucide-react");
5309
+ var import_lucide_react9 = require("lucide-react");
5252
5310
 
5253
5311
  // src/ui/link-modal/DestinationBreadcrumb.tsx
5254
- var import_lucide_react5 = require("lucide-react");
5255
- var import_jsx_runtime13 = require("react/jsx-runtime");
5312
+ var import_lucide_react6 = require("lucide-react");
5313
+ var import_jsx_runtime14 = require("react/jsx-runtime");
5256
5314
  function DestinationBreadcrumb({
5257
5315
  pageTitle,
5258
5316
  sectionLabel
5259
5317
  }) {
5260
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex w-full flex-col gap-2", children: [
5261
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "text-sm font-medium! text-foreground m-0", children: "Destination" }),
5262
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center gap-3", children: [
5263
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center gap-2", children: [
5264
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react5.File, { size: 16, className: "shrink-0 text-foreground", "aria-hidden": true }),
5265
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "text-sm font-medium leading-none text-foreground!", children: pageTitle })
5318
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex w-full flex-col gap-2", children: [
5319
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "text-sm font-medium! text-foreground m-0", children: "Destination" }),
5320
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center gap-3", children: [
5321
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center gap-2", children: [
5322
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react6.File, { size: 16, className: "shrink-0 text-foreground", "aria-hidden": true }),
5323
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "text-sm font-medium leading-none text-foreground!", children: pageTitle })
5266
5324
  ] }),
5267
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5268
- import_lucide_react5.ArrowRight,
5325
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5326
+ import_lucide_react6.ArrowRight,
5269
5327
  {
5270
5328
  size: 16,
5271
5329
  className: "shrink-0 text-muted-foreground",
5272
5330
  "aria-hidden": true
5273
5331
  }
5274
5332
  ),
5275
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
5276
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
5277
- import_lucide_react5.GalleryVertical,
5333
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
5334
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5335
+ import_lucide_react6.GalleryVertical,
5278
5336
  {
5279
5337
  size: 16,
5280
5338
  className: "shrink-0 text-foreground",
5281
5339
  "aria-hidden": true
5282
5340
  }
5283
5341
  ),
5284
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "truncate text-sm font-medium leading-none text-foreground", children: sectionLabel })
5342
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "truncate text-sm font-medium leading-none text-foreground", children: sectionLabel })
5285
5343
  ] })
5286
5344
  ] })
5287
5345
  ] });
5288
5346
  }
5289
5347
 
5290
5348
  // src/ui/link-modal/SectionTreeItem.tsx
5291
- var import_lucide_react6 = require("lucide-react");
5292
- var import_jsx_runtime14 = require("react/jsx-runtime");
5349
+ var import_lucide_react7 = require("lucide-react");
5350
+ var import_jsx_runtime15 = require("react/jsx-runtime");
5293
5351
  function SectionTreeItem({
5294
5352
  section,
5295
5353
  onSelect,
5296
5354
  selected
5297
5355
  }) {
5298
5356
  const interactive = Boolean(onSelect);
5299
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex h-9 w-full items-end pl-3", children: [
5300
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5357
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex h-9 w-full items-end pl-3", children: [
5358
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5301
5359
  "div",
5302
5360
  {
5303
5361
  className: "mr-[-1px] h-9 w-2 shrink-0 rounded-bl-sm border-b border-l border-border mb-4",
5304
5362
  "aria-hidden": true
5305
5363
  }
5306
5364
  ),
5307
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
5365
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
5308
5366
  "div",
5309
5367
  {
5310
5368
  role: interactive ? "button" : void 0,
@@ -5322,15 +5380,15 @@ function SectionTreeItem({
5322
5380
  interactive && selected && "border-primary"
5323
5381
  ),
5324
5382
  children: [
5325
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
5326
- import_lucide_react6.GalleryVertical,
5383
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5384
+ import_lucide_react7.GalleryVertical,
5327
5385
  {
5328
5386
  size: 16,
5329
5387
  className: "shrink-0 text-foreground",
5330
5388
  "aria-hidden": true
5331
5389
  }
5332
5390
  ),
5333
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "truncate text-sm font-normal leading-5 text-foreground", children: section.label })
5391
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "truncate text-sm font-normal leading-5 text-foreground", children: section.label })
5334
5392
  ]
5335
5393
  }
5336
5394
  )
@@ -5342,10 +5400,10 @@ var import_react4 = require("react");
5342
5400
 
5343
5401
  // src/ui/input.tsx
5344
5402
  var React8 = __toESM(require("react"), 1);
5345
- var import_jsx_runtime15 = require("react/jsx-runtime");
5403
+ var import_jsx_runtime16 = require("react/jsx-runtime");
5346
5404
  var Input = React8.forwardRef(
5347
5405
  ({ className, type, ...props }, ref) => {
5348
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
5406
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5349
5407
  "input",
5350
5408
  {
5351
5409
  type,
@@ -5364,9 +5422,9 @@ Input.displayName = "Input";
5364
5422
 
5365
5423
  // src/ui/label.tsx
5366
5424
  var import_radix_ui6 = require("radix-ui");
5367
- var import_jsx_runtime16 = require("react/jsx-runtime");
5425
+ var import_jsx_runtime17 = require("react/jsx-runtime");
5368
5426
  function Label({ className, ...props }) {
5369
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5427
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5370
5428
  import_radix_ui6.Label.Root,
5371
5429
  {
5372
5430
  "data-slot": "label",
@@ -5377,12 +5435,12 @@ function Label({ className, ...props }) {
5377
5435
  }
5378
5436
 
5379
5437
  // src/ui/link-modal/UrlOrPageInput.tsx
5380
- var import_lucide_react7 = require("lucide-react");
5381
- var import_jsx_runtime17 = require("react/jsx-runtime");
5438
+ var import_lucide_react8 = require("lucide-react");
5439
+ var import_jsx_runtime18 = require("react/jsx-runtime");
5382
5440
  function FieldChevron({
5383
5441
  onClick
5384
5442
  }) {
5385
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5443
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5386
5444
  "button",
5387
5445
  {
5388
5446
  type: "button",
@@ -5390,7 +5448,7 @@ function FieldChevron({
5390
5448
  onClick,
5391
5449
  "aria-label": "Open page list",
5392
5450
  tabIndex: -1,
5393
- children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react7.ChevronDown, { size: 16 })
5451
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.ChevronDown, { size: 16 })
5394
5452
  }
5395
5453
  );
5396
5454
  }
@@ -5451,19 +5509,19 @@ function UrlOrPageInput({
5451
5509
  "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]",
5452
5510
  urlError ? "border-destructive shadow-[0_0_0_1px_var(--ohw-destructive)]" : isFocused ? "border-primary shadow-[0_0_0_1px_var(--ohw-primary)]" : "border-input"
5453
5511
  );
5454
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex w-full flex-col gap-2 p-0", children: [
5455
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
5456
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { ref: rootRef, className: "relative w-full", children: [
5457
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { "data-ohw-link-field": true, className: fieldClassName, children: [
5458
- selectedPage ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "flex shrink-0 items-center pr-2", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5459
- import_lucide_react7.File,
5512
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex w-full flex-col gap-2 p-0", children: [
5513
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Label, { htmlFor: inputId, className: cn(urlError && "text-destructive"), children: "Destination" }),
5514
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { ref: rootRef, className: "relative w-full", children: [
5515
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { "data-ohw-link-field": true, className: fieldClassName, children: [
5516
+ selectedPage ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex shrink-0 items-center pr-2", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5517
+ import_lucide_react8.File,
5460
5518
  {
5461
5519
  size: 16,
5462
5520
  className: "shrink-0 text-foreground",
5463
5521
  "aria-hidden": true
5464
5522
  }
5465
5523
  ) }) : null,
5466
- 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)(
5524
+ 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)(
5467
5525
  Input,
5468
5526
  {
5469
5527
  ref: inputRef,
@@ -5489,7 +5547,7 @@ function UrlOrPageInput({
5489
5547
  )
5490
5548
  }
5491
5549
  ),
5492
- selectedPage && !readOnly ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5550
+ selectedPage && !readOnly ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5493
5551
  "button",
5494
5552
  {
5495
5553
  type: "button",
@@ -5497,26 +5555,26 @@ function UrlOrPageInput({
5497
5555
  onMouseDown: clearSelection,
5498
5556
  "aria-label": "Clear selected page",
5499
5557
  tabIndex: -1,
5500
- children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react7.X, { size: 16, "aria-hidden": true })
5558
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.X, { size: 16, "aria-hidden": true })
5501
5559
  }
5502
5560
  ) : null,
5503
- !readOnly ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(FieldChevron, { onClick: toggleDropdown }) : null
5561
+ !readOnly ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(FieldChevron, { onClick: toggleDropdown }) : null
5504
5562
  ] }),
5505
- dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5563
+ dropdownOpen && !readOnly && filteredPages.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5506
5564
  "div",
5507
5565
  {
5508
5566
  "data-ohw-link-page-dropdown": "",
5509
5567
  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",
5510
5568
  onMouseDown: (e) => e.preventDefault(),
5511
- children: filteredPages.map((page) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
5569
+ children: filteredPages.map((page) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
5512
5570
  "button",
5513
5571
  {
5514
5572
  type: "button",
5515
5573
  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",
5516
5574
  onClick: () => onPageSelect(page),
5517
5575
  children: [
5518
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react7.File, { size: 16, className: "shrink-0", "aria-hidden": true }),
5519
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "truncate", children: page.title })
5576
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.File, { size: 16, className: "shrink-0", "aria-hidden": true }),
5577
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "truncate", children: page.title })
5520
5578
  ]
5521
5579
  },
5522
5580
  page.path
@@ -5524,34 +5582,34 @@ function UrlOrPageInput({
5524
5582
  }
5525
5583
  ) : null
5526
5584
  ] }),
5527
- urlError ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-sm font-medium text-destructive", children: urlError }) : null
5585
+ urlError ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "text-sm font-medium text-destructive", children: urlError }) : null
5528
5586
  ] });
5529
5587
  }
5530
5588
 
5531
5589
  // src/ui/link-modal/LinkEditorPanel.tsx
5532
- var import_jsx_runtime18 = require("react/jsx-runtime");
5590
+ var import_jsx_runtime19 = require("react/jsx-runtime");
5533
5591
  function LinkEditorPanel({ state, onClose }) {
5534
5592
  const isCancel = state.secondaryLabel === "Cancel" || state.secondaryLabel === "Back to sections";
5535
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
5536
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DialogClose, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5593
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
5594
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(DialogClose, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5537
5595
  "button",
5538
5596
  {
5539
5597
  type: "button",
5540
5598
  className: "absolute right-[9px] top-[9px] rounded-sm p-1.5 text-foreground hover:bg-muted/50 h-7",
5541
5599
  "aria-label": "Close",
5542
5600
  onClick: onClose,
5543
- children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.X, { size: 16, "aria-hidden": true })
5601
+ children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react9.X, { size: 16, "aria-hidden": true })
5544
5602
  }
5545
5603
  ) }),
5546
- /* @__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 }) }),
5547
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex w-full flex-col gap-3 px-6 pb-8 pt-1", children: [
5548
- state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5604
+ /* @__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 }) }),
5605
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex w-full flex-col gap-3 px-6 pb-8 pt-1", children: [
5606
+ state.showBreadcrumb && state.selectedPage && state.selectedSection ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5549
5607
  DestinationBreadcrumb,
5550
5608
  {
5551
5609
  pageTitle: state.selectedPage.title,
5552
5610
  sectionLabel: state.selectedSection.label
5553
5611
  }
5554
- ) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5612
+ ) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5555
5613
  UrlOrPageInput,
5556
5614
  {
5557
5615
  value: state.searchValue,
@@ -5564,8 +5622,8 @@ function LinkEditorPanel({ state, onClose }) {
5564
5622
  urlError: state.urlError
5565
5623
  }
5566
5624
  ),
5567
- state.showChooseSection ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex flex-col justify-center gap-2", children: [
5568
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5625
+ state.showChooseSection ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex flex-col justify-center gap-2", children: [
5626
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5569
5627
  Button,
5570
5628
  {
5571
5629
  type: "button",
@@ -5576,15 +5634,15 @@ function LinkEditorPanel({ state, onClose }) {
5576
5634
  children: "Choose a section"
5577
5635
  }
5578
5636
  ),
5579
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
5580
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react8.Info, { size: 16, className: "shrink-0", "aria-hidden": true }),
5581
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { children: "Pick a section this link should scroll to." })
5637
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-center gap-1 text-sm text-muted-foreground", children: [
5638
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react9.Info, { size: 16, className: "shrink-0", "aria-hidden": true }),
5639
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { children: "Pick a section this link should scroll to." })
5582
5640
  ] })
5583
5641
  ] }) : null,
5584
- state.showSectionRow && state.selectedSection ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(SectionTreeItem, { section: state.selectedSection, selected: true }) : null
5642
+ state.showSectionRow && state.selectedSection ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(SectionTreeItem, { section: state.selectedSection, selected: true }) : null
5585
5643
  ] }),
5586
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(DialogFooter, { className: "w-full px-6 pb-6", children: [
5587
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5644
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(DialogFooter, { className: "w-full px-6 pb-6", children: [
5645
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5588
5646
  Button,
5589
5647
  {
5590
5648
  type: "button",
@@ -5599,7 +5657,7 @@ function LinkEditorPanel({ state, onClose }) {
5599
5657
  children: state.secondaryLabel
5600
5658
  }
5601
5659
  ),
5602
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
5660
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5603
5661
  Button,
5604
5662
  {
5605
5663
  type: "button",
@@ -5620,9 +5678,9 @@ function LinkEditorPanel({ state, onClose }) {
5620
5678
  // src/ui/link-modal/SectionPickerOverlay.tsx
5621
5679
  var import_react5 = require("react");
5622
5680
  var import_react_dom = require("react-dom");
5623
- var import_lucide_react9 = require("lucide-react");
5681
+ var import_lucide_react10 = require("lucide-react");
5624
5682
  var import_navigation = require("next/navigation");
5625
- var import_jsx_runtime19 = require("react/jsx-runtime");
5683
+ var import_jsx_runtime20 = require("react/jsx-runtime");
5626
5684
  var DIM_OVERLAY = "rgba(0, 0, 0, 0.45)";
5627
5685
  function rectsEqual(a, b) {
5628
5686
  if (a.size !== b.size) return false;
@@ -5845,7 +5903,7 @@ function SectionPickerOverlay({
5845
5903
  const portalRoot = typeof document !== "undefined" ? document.querySelector("[data-ohw-bridge-root]") ?? document.body : null;
5846
5904
  if (!portalRoot) return null;
5847
5905
  return (0, import_react_dom.createPortal)(
5848
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
5906
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
5849
5907
  "div",
5850
5908
  {
5851
5909
  "data-ohw-section-picker": "",
@@ -5855,12 +5913,12 @@ function SectionPickerOverlay({
5855
5913
  role: "dialog",
5856
5914
  "aria-label": "Choose a section",
5857
5915
  children: [
5858
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5916
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
5859
5917
  "div",
5860
5918
  {
5861
5919
  className: "pointer-events-auto fixed left-5 z-[2]",
5862
5920
  style: { top: chromeClip.top + 20 },
5863
- children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
5921
+ children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
5864
5922
  Button,
5865
5923
  {
5866
5924
  type: "button",
@@ -5869,14 +5927,14 @@ function SectionPickerOverlay({
5869
5927
  className: "h-8 min-w-0 gap-1 border-border bg-background px-2 py-1.5 shadow-sm hover:bg-muted cursor-pointer",
5870
5928
  onClick: onBack,
5871
5929
  children: [
5872
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react9.ArrowLeft, { className: "size-4 shrink-0", "aria-hidden": true }),
5930
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react10.ArrowLeft, { className: "size-4 shrink-0", "aria-hidden": true }),
5873
5931
  "Back"
5874
5932
  ]
5875
5933
  }
5876
5934
  )
5877
5935
  }
5878
5936
  ),
5879
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5937
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
5880
5938
  "div",
5881
5939
  {
5882
5940
  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",
@@ -5889,7 +5947,7 @@ function SectionPickerOverlay({
5889
5947
  children: "Click on section to select"
5890
5948
  }
5891
5949
  ),
5892
- !isOnTargetPage ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5950
+ !isOnTargetPage ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
5893
5951
  "div",
5894
5952
  {
5895
5953
  className: "pointer-events-none fixed left-1/2 z-[1] -translate-x-1/2 rounded-md bg-background/90 px-3 py-2 text-sm text-muted-foreground shadow-sm",
@@ -5897,13 +5955,13 @@ function SectionPickerOverlay({
5897
5955
  children: "Loading page preview\u2026"
5898
5956
  }
5899
5957
  ) : null,
5900
- 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,
5958
+ 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,
5901
5959
  isOnTargetPage ? liveSections.map((section) => {
5902
5960
  const rect = rects.get(section.id);
5903
5961
  if (!rect || rect.width <= 0 || rect.height <= 0) return null;
5904
5962
  const isSelected = selectedId === section.id;
5905
5963
  const isLit = isSelected || hoveredId === section.id;
5906
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5964
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
5907
5965
  "button",
5908
5966
  {
5909
5967
  type: "button",
@@ -5917,13 +5975,13 @@ function SectionPickerOverlay({
5917
5975
  },
5918
5976
  "aria-label": `Select section ${section.label}`,
5919
5977
  onClick: () => handleSelect(section),
5920
- children: isSelected ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
5978
+ children: isSelected ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
5921
5979
  "span",
5922
5980
  {
5923
5981
  className: "absolute right-3 top-3 flex size-8 items-center justify-center rounded-full text-white",
5924
5982
  style: { backgroundColor: "var(--ohw-primary, #0885fe)" },
5925
5983
  "aria-hidden": true,
5926
- children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react9.Check, { className: "size-5" })
5984
+ children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react10.Check, { className: "size-5" })
5927
5985
  }
5928
5986
  ) : null
5929
5987
  },
@@ -6102,7 +6160,7 @@ function useLinkModalState({
6102
6160
  }
6103
6161
 
6104
6162
  // src/ui/link-modal/LinkPopover.tsx
6105
- var import_jsx_runtime20 = require("react/jsx-runtime");
6163
+ var import_jsx_runtime21 = require("react/jsx-runtime");
6106
6164
  function postToParent(data) {
6107
6165
  window.parent?.postMessage(data, "*");
6108
6166
  }
@@ -6198,15 +6256,15 @@ function LinkPopover({
6198
6256
  );
6199
6257
  };
6200
6258
  }, [open, sectionPickerActive]);
6201
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
6202
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6259
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
6260
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6203
6261
  Dialog2,
6204
6262
  {
6205
6263
  open: open && !sectionPickerActive,
6206
6264
  onOpenChange: (next) => {
6207
6265
  if (!next) onClose?.();
6208
6266
  },
6209
- children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6267
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6210
6268
  DialogContent,
6211
6269
  {
6212
6270
  ref: panelRef,
@@ -6216,12 +6274,12 @@ function LinkPopover({
6216
6274
  "data-ohw-bridge": "",
6217
6275
  showCloseButton: false,
6218
6276
  className: "gap-0 p-0 w-full max-w-[448px] pointer-events-auto z-[2147483646] overflow-visible",
6219
- children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(LinkEditorPanel, { state, onClose })
6277
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(LinkEditorPanel, { state, onClose })
6220
6278
  }
6221
6279
  )
6222
6280
  }
6223
6281
  ),
6224
- sectionPickerActive && state.selectedPage ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
6282
+ sectionPickerActive && state.selectedPage ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6225
6283
  SectionPickerOverlay,
6226
6284
  {
6227
6285
  pagePath: state.selectedPage.path,
@@ -6527,15 +6585,99 @@ function insertNavbarItem(href, label, afterAnchor = null) {
6527
6585
  };
6528
6586
  }
6529
6587
 
6588
+ // src/lib/carousel.ts
6589
+ var import_react8 = require("react");
6590
+ var CAROUSEL_ATTR = "data-ohw-carousel";
6591
+ var CAROUSEL_VALUE_ATTR = "data-ohw-carousel-value";
6592
+ var CAROUSEL_SLIDE_ATTR = "data-ohw-carousel-slide";
6593
+ var CAROUSEL_EVENT = "ohw:carousel-change";
6594
+ function listCarouselKeys() {
6595
+ const keys = /* @__PURE__ */ new Set();
6596
+ document.querySelectorAll(`[${CAROUSEL_ATTR}]`).forEach((el) => {
6597
+ const key = el.getAttribute("data-ohw-key");
6598
+ if (key) keys.add(key);
6599
+ });
6600
+ return [...keys];
6601
+ }
6602
+ function containersForKey(key) {
6603
+ return Array.from(
6604
+ document.querySelectorAll(`[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`)
6605
+ );
6606
+ }
6607
+ function isCarouselKey(key) {
6608
+ return containersForKey(key).length > 0;
6609
+ }
6610
+ function parseSlides(raw) {
6611
+ if (!raw) return [];
6612
+ try {
6613
+ const parsed = JSON.parse(raw);
6614
+ if (!Array.isArray(parsed)) return [];
6615
+ return parsed.filter((s) => Boolean(s) && typeof s === "object").map((s) => ({ src: String(s.src ?? ""), alt: String(s.alt ?? "") }));
6616
+ } catch {
6617
+ return [];
6618
+ }
6619
+ }
6620
+ function readCarouselValue(key) {
6621
+ const container = containersForKey(key)[0];
6622
+ if (!container) return [];
6623
+ const fromAttr = parseSlides(container.getAttribute(CAROUSEL_VALUE_ATTR));
6624
+ if (fromAttr.length > 0) return fromAttr;
6625
+ return Array.from(container.querySelectorAll(`[${CAROUSEL_SLIDE_ATTR}]`)).filter((slide) => slide.closest(`[${CAROUSEL_ATTR}]`) === container).sort((a, b) => slideIndex(a) - slideIndex(b)).map((slide) => {
6626
+ const img = slide instanceof HTMLImageElement ? slide : slide.querySelector("img");
6627
+ return { src: img?.src ?? "", alt: img?.alt ?? "" };
6628
+ });
6629
+ }
6630
+ function slideIndex(el) {
6631
+ const raw = el.getAttribute(CAROUSEL_SLIDE_ATTR);
6632
+ const n = raw ? parseInt(raw, 10) : NaN;
6633
+ return Number.isFinite(n) ? n : 0;
6634
+ }
6635
+ function applyCarouselValue(key, slides) {
6636
+ const value = JSON.stringify(slides);
6637
+ for (const container of containersForKey(key)) {
6638
+ if (container.getAttribute(CAROUSEL_VALUE_ATTR) === value) continue;
6639
+ container.setAttribute(CAROUSEL_VALUE_ATTR, value);
6640
+ container.dispatchEvent(
6641
+ new CustomEvent(CAROUSEL_EVENT, { detail: { images: slides } })
6642
+ );
6643
+ }
6644
+ }
6645
+ function applyCarouselNode(key, val) {
6646
+ if (!isCarouselKey(key)) return false;
6647
+ applyCarouselValue(key, parseSlides(val));
6648
+ return true;
6649
+ }
6650
+ function useOhwCarousel(key, initial) {
6651
+ const [images, setImages] = (0, import_react8.useState)(initial);
6652
+ (0, import_react8.useEffect)(() => {
6653
+ const el = document.querySelector(
6654
+ `[${CAROUSEL_ATTR}][data-ohw-key="${CSS.escape(key)}"]`
6655
+ );
6656
+ if (!el) return;
6657
+ const onChange = (e) => {
6658
+ const detail = e.detail;
6659
+ if (Array.isArray(detail?.images)) setImages(detail.images);
6660
+ };
6661
+ el.addEventListener(CAROUSEL_EVENT, onChange);
6662
+ return () => el.removeEventListener(CAROUSEL_EVENT, onChange);
6663
+ }, [key]);
6664
+ const bind = {
6665
+ [CAROUSEL_ATTR]: "",
6666
+ "data-ohw-key": key,
6667
+ [CAROUSEL_VALUE_ATTR]: JSON.stringify(images)
6668
+ };
6669
+ return { images, setImages, bind };
6670
+ }
6671
+
6530
6672
  // src/ui/navbar-container-chrome.tsx
6531
- var import_lucide_react10 = require("lucide-react");
6532
- var import_jsx_runtime21 = require("react/jsx-runtime");
6673
+ var import_lucide_react11 = require("lucide-react");
6674
+ var import_jsx_runtime22 = require("react/jsx-runtime");
6533
6675
  function NavbarContainerChrome({
6534
6676
  rect,
6535
6677
  onAdd
6536
6678
  }) {
6537
6679
  const chromeGap = 6;
6538
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6680
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
6539
6681
  "div",
6540
6682
  {
6541
6683
  "data-ohw-navbar-container-chrome": "",
@@ -6547,7 +6689,7 @@ function NavbarContainerChrome({
6547
6689
  width: rect.width + chromeGap * 2,
6548
6690
  height: rect.height + chromeGap * 2
6549
6691
  },
6550
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
6692
+ children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
6551
6693
  "button",
6552
6694
  {
6553
6695
  type: "button",
@@ -6564,7 +6706,7 @@ function NavbarContainerChrome({
6564
6706
  e.stopPropagation();
6565
6707
  onAdd();
6566
6708
  },
6567
- children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react10.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
6709
+ children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react11.Plus, { className: "size-4 shrink-0 text-foreground", "aria-hidden": true })
6568
6710
  }
6569
6711
  )
6570
6712
  }
@@ -6572,7 +6714,7 @@ function NavbarContainerChrome({
6572
6714
  }
6573
6715
 
6574
6716
  // src/ui/badge.tsx
6575
- var import_jsx_runtime22 = require("react/jsx-runtime");
6717
+ var import_jsx_runtime23 = require("react/jsx-runtime");
6576
6718
  var badgeVariants = cva(
6577
6719
  "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",
6578
6720
  {
@@ -6590,12 +6732,12 @@ var badgeVariants = cva(
6590
6732
  }
6591
6733
  );
6592
6734
  function Badge({ className, variant, ...props }) {
6593
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
6735
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: cn(badgeVariants({ variant }), className), ...props });
6594
6736
  }
6595
6737
 
6596
6738
  // src/OhhwellsBridge.tsx
6597
- var import_lucide_react11 = require("lucide-react");
6598
- var import_jsx_runtime23 = require("react/jsx-runtime");
6739
+ var import_lucide_react12 = require("lucide-react");
6740
+ var import_jsx_runtime24 = require("react/jsx-runtime");
6599
6741
  var PRIMARY2 = "#0885FE";
6600
6742
  var IMAGE_FADE_MS = 300;
6601
6743
  function runOpacityFade(el, onDone) {
@@ -6774,7 +6916,7 @@ function mountSchedulingWidget(insertAfter, notifyOnConnect = false, scheduleId,
6774
6916
  const root = (0, import_client.createRoot)(container);
6775
6917
  (0, import_react_dom2.flushSync)(() => {
6776
6918
  root.render(
6777
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6919
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
6778
6920
  SchedulingWidget,
6779
6921
  {
6780
6922
  notifyOnConnect,
@@ -6871,6 +7013,9 @@ function collectEditableNodes() {
6871
7013
  nodes.push({ key: `${key}${VIDEO_AUTOPLAY_SUFFIX}`, type: "video-setting", text: String(video.autoplay) });
6872
7014
  nodes.push({ key: `${key}${VIDEO_MUTED_SUFFIX}`, type: "video-setting", text: String(video.muted) });
6873
7015
  });
7016
+ for (const key of listCarouselKeys()) {
7017
+ nodes.push({ key, type: "carousel", text: JSON.stringify(readCarouselValue(key)) });
7018
+ }
6874
7019
  return nodes;
6875
7020
  }
6876
7021
  function isMediaEditable(el) {
@@ -7257,7 +7402,7 @@ function EditGlowChrome({
7257
7402
  dragDisabled = false
7258
7403
  }) {
7259
7404
  const GAP = 6;
7260
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
7405
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
7261
7406
  "div",
7262
7407
  {
7263
7408
  ref: elRef,
@@ -7272,7 +7417,7 @@ function EditGlowChrome({
7272
7417
  zIndex: 2147483646
7273
7418
  },
7274
7419
  children: [
7275
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
7420
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
7276
7421
  "div",
7277
7422
  {
7278
7423
  style: {
@@ -7285,7 +7430,7 @@ function EditGlowChrome({
7285
7430
  }
7286
7431
  }
7287
7432
  ),
7288
- reorderHrefKey && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
7433
+ reorderHrefKey && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
7289
7434
  "div",
7290
7435
  {
7291
7436
  "data-ohw-drag-handle-container": "",
@@ -7297,7 +7442,7 @@ function EditGlowChrome({
7297
7442
  transform: "translate(calc(-100% - 7px), -50%)",
7298
7443
  pointerEvents: dragDisabled ? "none" : "auto"
7299
7444
  },
7300
- children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
7445
+ children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
7301
7446
  DragHandle,
7302
7447
  {
7303
7448
  "aria-label": `Reorder ${reorderHrefKey}`,
@@ -7401,7 +7546,7 @@ function FloatingToolbar({
7401
7546
  onEditLink
7402
7547
  }) {
7403
7548
  const { top, left, transform } = calcToolbarPos(rect, parentScroll, 330);
7404
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
7549
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
7405
7550
  "div",
7406
7551
  {
7407
7552
  ref: elRef,
@@ -7422,12 +7567,12 @@ function FloatingToolbar({
7422
7567
  fontFamily: "sans-serif",
7423
7568
  pointerEvents: "auto"
7424
7569
  },
7425
- children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(CustomToolbar, { children: [
7426
- TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_react8.default.Fragment, { children: [
7427
- gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(CustomToolbarDivider, {}),
7570
+ children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(CustomToolbar, { children: [
7571
+ TOOLBAR_GROUPS.map((btns, gi) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_react9.default.Fragment, { children: [
7572
+ gi > 0 && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(CustomToolbarDivider, {}),
7428
7573
  btns.map((btn) => {
7429
7574
  const isActive = activeCommands.has(btn.cmd);
7430
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
7575
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
7431
7576
  CustomToolbarButton,
7432
7577
  {
7433
7578
  title: btn.title,
@@ -7436,7 +7581,7 @@ function FloatingToolbar({
7436
7581
  e.preventDefault();
7437
7582
  onCommand(btn.cmd);
7438
7583
  },
7439
- children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
7584
+ children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
7440
7585
  "svg",
7441
7586
  {
7442
7587
  width: "16",
@@ -7457,7 +7602,7 @@ function FloatingToolbar({
7457
7602
  );
7458
7603
  })
7459
7604
  ] }, gi)),
7460
- showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
7605
+ showEditLink ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
7461
7606
  CustomToolbarButton,
7462
7607
  {
7463
7608
  type: "button",
@@ -7471,7 +7616,7 @@ function FloatingToolbar({
7471
7616
  e.preventDefault();
7472
7617
  e.stopPropagation();
7473
7618
  },
7474
- children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react11.Link, { className: "size-4 shrink-0", "aria-hidden": true })
7619
+ children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react12.Link, { className: "size-4 shrink-0", "aria-hidden": true })
7475
7620
  }
7476
7621
  ) : null
7477
7622
  ] })
@@ -7488,7 +7633,7 @@ function StateToggle({
7488
7633
  states,
7489
7634
  onStateChange
7490
7635
  }) {
7491
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
7636
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
7492
7637
  ToggleGroup,
7493
7638
  {
7494
7639
  "data-ohw-state-toggle": "",
@@ -7502,7 +7647,7 @@ function StateToggle({
7502
7647
  left: rect.right - 8,
7503
7648
  transform: "translateX(-100%)"
7504
7649
  },
7505
- children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
7650
+ children: states.map((state) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ToggleGroupItem, { value: state, size: "sm", children: state }, state))
7506
7651
  }
7507
7652
  );
7508
7653
  }
@@ -7529,8 +7674,8 @@ function OhhwellsBridge() {
7529
7674
  const router = (0, import_navigation2.useRouter)();
7530
7675
  const searchParams = (0, import_navigation2.useSearchParams)();
7531
7676
  const isEditMode = isEditSessionActive();
7532
- const [bridgeRoot, setBridgeRoot] = (0, import_react8.useState)(null);
7533
- (0, import_react8.useEffect)(() => {
7677
+ const [bridgeRoot, setBridgeRoot] = (0, import_react9.useState)(null);
7678
+ (0, import_react9.useEffect)(() => {
7534
7679
  const figtreeFontId = "ohw-figtree-font";
7535
7680
  if (!document.getElementById(figtreeFontId)) {
7536
7681
  const preconnect1 = Object.assign(document.createElement("link"), { rel: "preconnect", href: "https://fonts.googleapis.com" });
@@ -7558,91 +7703,92 @@ function OhhwellsBridge() {
7558
7703
  const subdomainFromQuery = searchParams.get("subdomain");
7559
7704
  const subdomain = resolveSubdomain(subdomainFromQuery);
7560
7705
  useLinkHrefGuardian(pathname, subdomain, isEditMode);
7561
- const postToParent2 = (0, import_react8.useCallback)((data) => {
7706
+ const postToParent2 = (0, import_react9.useCallback)((data) => {
7562
7707
  if (typeof window !== "undefined" && window.parent !== window) {
7563
7708
  window.parent.postMessage(data, "*");
7564
7709
  }
7565
7710
  }, []);
7566
- const [fetchState, setFetchState] = (0, import_react8.useState)("idle");
7567
- const autoSaveTimers = (0, import_react8.useRef)(/* @__PURE__ */ new Map());
7568
- const activeElRef = (0, import_react8.useRef)(null);
7569
- const selectedElRef = (0, import_react8.useRef)(null);
7570
- const originalContentRef = (0, import_react8.useRef)(null);
7571
- const activeStateElRef = (0, import_react8.useRef)(null);
7572
- const parentScrollRef = (0, import_react8.useRef)(null);
7573
- const visibleViewportRef = (0, import_react8.useRef)(null);
7574
- const [dialogPortalContainer, setDialogPortalContainer] = (0, import_react8.useState)(null);
7575
- const attachVisibleViewport = (0, import_react8.useCallback)((node) => {
7711
+ const [fetchState, setFetchState] = (0, import_react9.useState)("idle");
7712
+ const autoSaveTimers = (0, import_react9.useRef)(/* @__PURE__ */ new Map());
7713
+ const activeElRef = (0, import_react9.useRef)(null);
7714
+ const selectedElRef = (0, import_react9.useRef)(null);
7715
+ const originalContentRef = (0, import_react9.useRef)(null);
7716
+ const activeStateElRef = (0, import_react9.useRef)(null);
7717
+ const parentScrollRef = (0, import_react9.useRef)(null);
7718
+ const visibleViewportRef = (0, import_react9.useRef)(null);
7719
+ const [dialogPortalContainer, setDialogPortalContainer] = (0, import_react9.useState)(null);
7720
+ const attachVisibleViewport = (0, import_react9.useCallback)((node) => {
7576
7721
  visibleViewportRef.current = node;
7577
7722
  setDialogPortalContainer(node);
7578
7723
  if (node) applyVisibleViewport(node, parentScrollRef.current);
7579
7724
  }, []);
7580
- const toolbarElRef = (0, import_react8.useRef)(null);
7581
- const glowElRef = (0, import_react8.useRef)(null);
7582
- const hoveredImageRef = (0, import_react8.useRef)(null);
7583
- const hoveredImageHasTextOverlapRef = (0, import_react8.useRef)(false);
7584
- const dragOverElRef = (0, import_react8.useRef)(null);
7585
- const [mediaHover, setMediaHover] = (0, import_react8.useState)(null);
7586
- const [uploadingRects, setUploadingRects] = (0, import_react8.useState)({});
7587
- const hoveredGapRef = (0, import_react8.useRef)(null);
7588
- const imageUnhoverTimerRef = (0, import_react8.useRef)(null);
7589
- const imageShowTimerRef = (0, import_react8.useRef)(null);
7590
- const editStylesRef = (0, import_react8.useRef)(null);
7591
- const activateRef = (0, import_react8.useRef)(() => {
7725
+ const toolbarElRef = (0, import_react9.useRef)(null);
7726
+ const glowElRef = (0, import_react9.useRef)(null);
7727
+ const hoveredImageRef = (0, import_react9.useRef)(null);
7728
+ const hoveredImageHasTextOverlapRef = (0, import_react9.useRef)(false);
7729
+ const dragOverElRef = (0, import_react9.useRef)(null);
7730
+ const [mediaHover, setMediaHover] = (0, import_react9.useState)(null);
7731
+ const [carouselHover, setCarouselHover] = (0, import_react9.useState)(null);
7732
+ const [uploadingRects, setUploadingRects] = (0, import_react9.useState)({});
7733
+ const hoveredGapRef = (0, import_react9.useRef)(null);
7734
+ const imageUnhoverTimerRef = (0, import_react9.useRef)(null);
7735
+ const imageShowTimerRef = (0, import_react9.useRef)(null);
7736
+ const editStylesRef = (0, import_react9.useRef)(null);
7737
+ const activateRef = (0, import_react9.useRef)(() => {
7592
7738
  });
7593
- const deactivateRef = (0, import_react8.useRef)(() => {
7739
+ const deactivateRef = (0, import_react9.useRef)(() => {
7594
7740
  });
7595
- const selectRef = (0, import_react8.useRef)(() => {
7741
+ const selectRef = (0, import_react9.useRef)(() => {
7596
7742
  });
7597
- const selectFrameRef = (0, import_react8.useRef)(() => {
7743
+ const selectFrameRef = (0, import_react9.useRef)(() => {
7598
7744
  });
7599
- const deselectRef = (0, import_react8.useRef)(() => {
7745
+ const deselectRef = (0, import_react9.useRef)(() => {
7600
7746
  });
7601
- const reselectNavigationItemRef = (0, import_react8.useRef)(() => {
7747
+ const reselectNavigationItemRef = (0, import_react9.useRef)(() => {
7602
7748
  });
7603
- const commitNavigationTextEditRef = (0, import_react8.useRef)(() => {
7749
+ const commitNavigationTextEditRef = (0, import_react9.useRef)(() => {
7604
7750
  });
7605
- const refreshActiveCommandsRef = (0, import_react8.useRef)(() => {
7751
+ const refreshActiveCommandsRef = (0, import_react9.useRef)(() => {
7606
7752
  });
7607
- const postToParentRef = (0, import_react8.useRef)(postToParent2);
7753
+ const postToParentRef = (0, import_react9.useRef)(postToParent2);
7608
7754
  postToParentRef.current = postToParent2;
7609
- const sectionsLoadedRef = (0, import_react8.useRef)(false);
7610
- const pendingScheduleConfigRequests = (0, import_react8.useRef)([]);
7611
- const [toolbarRect, setToolbarRect] = (0, import_react8.useState)(null);
7612
- const [toolbarVariant, setToolbarVariant] = (0, import_react8.useState)("none");
7613
- const toolbarVariantRef = (0, import_react8.useRef)("none");
7755
+ const sectionsLoadedRef = (0, import_react9.useRef)(false);
7756
+ const pendingScheduleConfigRequests = (0, import_react9.useRef)([]);
7757
+ const [toolbarRect, setToolbarRect] = (0, import_react9.useState)(null);
7758
+ const [toolbarVariant, setToolbarVariant] = (0, import_react9.useState)("none");
7759
+ const toolbarVariantRef = (0, import_react9.useRef)("none");
7614
7760
  toolbarVariantRef.current = toolbarVariant;
7615
- const [reorderHrefKey, setReorderHrefKey] = (0, import_react8.useState)(null);
7616
- const [reorderDragDisabled, setReorderDragDisabled] = (0, import_react8.useState)(false);
7617
- const [toggleState, setToggleState] = (0, import_react8.useState)(null);
7618
- const [maxBadge, setMaxBadge] = (0, import_react8.useState)(null);
7619
- const [activeCommands, setActiveCommands] = (0, import_react8.useState)(/* @__PURE__ */ new Set());
7620
- const [sectionGap, setSectionGap] = (0, import_react8.useState)(null);
7621
- const [toolbarShowEditLink, setToolbarShowEditLink] = (0, import_react8.useState)(false);
7622
- const hoveredNavContainerRef = (0, import_react8.useRef)(null);
7623
- const [hoveredNavContainerRect, setHoveredNavContainerRect] = (0, import_react8.useState)(null);
7624
- const hoveredItemElRef = (0, import_react8.useRef)(null);
7625
- const [hoveredItemRect, setHoveredItemRect] = (0, import_react8.useState)(null);
7626
- const siblingHintElRef = (0, import_react8.useRef)(null);
7627
- const [siblingHintRect, setSiblingHintRect] = (0, import_react8.useState)(null);
7628
- const [isItemDragging, setIsItemDragging] = (0, import_react8.useState)(false);
7629
- const [linkPopover, setLinkPopover] = (0, import_react8.useState)(null);
7630
- const linkPopoverSessionRef = (0, import_react8.useRef)(null);
7631
- const addNavAfterAnchorRef = (0, import_react8.useRef)(null);
7632
- const editContentRef = (0, import_react8.useRef)({});
7633
- const [sitePages, setSitePages] = (0, import_react8.useState)([]);
7634
- const [sectionsByPath, setSectionsByPath] = (0, import_react8.useState)({});
7635
- const sectionsPrefetchGenRef = (0, import_react8.useRef)(0);
7636
- const setLinkPopoverRef = (0, import_react8.useRef)(setLinkPopover);
7637
- const linkPopoverPanelRef = (0, import_react8.useRef)(null);
7638
- const linkPopoverOpenRef = (0, import_react8.useRef)(false);
7639
- const linkPopoverGraceUntilRef = (0, import_react8.useRef)(0);
7761
+ const [reorderHrefKey, setReorderHrefKey] = (0, import_react9.useState)(null);
7762
+ const [reorderDragDisabled, setReorderDragDisabled] = (0, import_react9.useState)(false);
7763
+ const [toggleState, setToggleState] = (0, import_react9.useState)(null);
7764
+ const [maxBadge, setMaxBadge] = (0, import_react9.useState)(null);
7765
+ const [activeCommands, setActiveCommands] = (0, import_react9.useState)(/* @__PURE__ */ new Set());
7766
+ const [sectionGap, setSectionGap] = (0, import_react9.useState)(null);
7767
+ const [toolbarShowEditLink, setToolbarShowEditLink] = (0, import_react9.useState)(false);
7768
+ const hoveredNavContainerRef = (0, import_react9.useRef)(null);
7769
+ const [hoveredNavContainerRect, setHoveredNavContainerRect] = (0, import_react9.useState)(null);
7770
+ const hoveredItemElRef = (0, import_react9.useRef)(null);
7771
+ const [hoveredItemRect, setHoveredItemRect] = (0, import_react9.useState)(null);
7772
+ const siblingHintElRef = (0, import_react9.useRef)(null);
7773
+ const [siblingHintRect, setSiblingHintRect] = (0, import_react9.useState)(null);
7774
+ const [isItemDragging, setIsItemDragging] = (0, import_react9.useState)(false);
7775
+ const [linkPopover, setLinkPopover] = (0, import_react9.useState)(null);
7776
+ const linkPopoverSessionRef = (0, import_react9.useRef)(null);
7777
+ const addNavAfterAnchorRef = (0, import_react9.useRef)(null);
7778
+ const editContentRef = (0, import_react9.useRef)({});
7779
+ const [sitePages, setSitePages] = (0, import_react9.useState)([]);
7780
+ const [sectionsByPath, setSectionsByPath] = (0, import_react9.useState)({});
7781
+ const sectionsPrefetchGenRef = (0, import_react9.useRef)(0);
7782
+ const setLinkPopoverRef = (0, import_react9.useRef)(setLinkPopover);
7783
+ const linkPopoverPanelRef = (0, import_react9.useRef)(null);
7784
+ const linkPopoverOpenRef = (0, import_react9.useRef)(false);
7785
+ const linkPopoverGraceUntilRef = (0, import_react9.useRef)(0);
7640
7786
  setLinkPopoverRef.current = setLinkPopover;
7641
7787
  linkPopoverSessionRef.current = linkPopover;
7642
7788
  const bumpLinkPopoverGrace = () => {
7643
7789
  linkPopoverGraceUntilRef.current = Date.now() + 350;
7644
7790
  };
7645
- const runSectionsPrefetch = (0, import_react8.useCallback)((pages) => {
7791
+ const runSectionsPrefetch = (0, import_react9.useCallback)((pages) => {
7646
7792
  if (!isEditMode || shouldUseDevFixtures() || pages.length === 0) return;
7647
7793
  const gen = ++sectionsPrefetchGenRef.current;
7648
7794
  const paths = pages.map((p) => p.path);
@@ -7661,9 +7807,9 @@ function OhhwellsBridge() {
7661
7807
  );
7662
7808
  });
7663
7809
  }, [isEditMode, pathname]);
7664
- const runSectionsPrefetchRef = (0, import_react8.useRef)(runSectionsPrefetch);
7810
+ const runSectionsPrefetchRef = (0, import_react9.useRef)(runSectionsPrefetch);
7665
7811
  runSectionsPrefetchRef.current = runSectionsPrefetch;
7666
- (0, import_react8.useEffect)(() => {
7812
+ (0, import_react9.useEffect)(() => {
7667
7813
  if (!linkPopover) return;
7668
7814
  if (hoveredImageRef.current) {
7669
7815
  hoveredImageRef.current = null;
@@ -7673,7 +7819,7 @@ function OhhwellsBridge() {
7673
7819
  setSectionGap(null);
7674
7820
  postToParent2({ type: "ow:image-unhover" });
7675
7821
  }, [linkPopover, postToParent2]);
7676
- (0, import_react8.useEffect)(() => {
7822
+ (0, import_react9.useEffect)(() => {
7677
7823
  if (!isEditMode) return;
7678
7824
  const useFixtures = shouldUseDevFixtures();
7679
7825
  if (useFixtures) {
@@ -7697,14 +7843,14 @@ function OhhwellsBridge() {
7697
7843
  if (!useFixtures) postToParent2({ type: "ow:request-site-pages" });
7698
7844
  return () => window.removeEventListener("message", onSitePages);
7699
7845
  }, [isEditMode, postToParent2]);
7700
- (0, import_react8.useEffect)(() => {
7846
+ (0, import_react9.useEffect)(() => {
7701
7847
  if (!isEditMode || shouldUseDevFixtures()) return;
7702
7848
  void loadAllSectionsManifest().then((manifest) => {
7703
7849
  if (Object.keys(manifest).length === 0) return;
7704
7850
  setSectionsByPath((prev) => ({ ...manifest, ...prev }));
7705
7851
  });
7706
7852
  }, [isEditMode]);
7707
- (0, import_react8.useEffect)(() => {
7853
+ (0, import_react9.useEffect)(() => {
7708
7854
  const update = () => {
7709
7855
  const el = activeElRef.current ?? selectedElRef.current;
7710
7856
  if (el) setToolbarRect(getEditMeasureEl(el).getBoundingClientRect());
@@ -7728,10 +7874,10 @@ function OhhwellsBridge() {
7728
7874
  vvp.removeEventListener("resize", update);
7729
7875
  };
7730
7876
  }, []);
7731
- const refreshStateRules = (0, import_react8.useCallback)(() => {
7877
+ const refreshStateRules = (0, import_react9.useCallback)(() => {
7732
7878
  editStylesRef.current?.forceHover && (editStylesRef.current.forceHover.textContent = collectStateRules());
7733
7879
  }, []);
7734
- const processConfigRequest = (0, import_react8.useCallback)((insertAfterVal) => {
7880
+ const processConfigRequest = (0, import_react9.useCallback)((insertAfterVal) => {
7735
7881
  const tracker = getSectionsTracker();
7736
7882
  let entries = [];
7737
7883
  try {
@@ -7754,7 +7900,7 @@ function OhhwellsBridge() {
7754
7900
  }
7755
7901
  window.postMessage({ type: "ow:schedule-config", insertAfter: insertAfterVal, scheduleId: null }, "*");
7756
7902
  }, [isEditMode]);
7757
- const deactivate = (0, import_react8.useCallback)(() => {
7903
+ const deactivate = (0, import_react9.useCallback)(() => {
7758
7904
  const el = activeElRef.current;
7759
7905
  if (!el) return;
7760
7906
  const key = el.dataset.ohwKey;
@@ -7785,7 +7931,7 @@ function OhhwellsBridge() {
7785
7931
  setToolbarShowEditLink(false);
7786
7932
  postToParent2({ type: "ow:exit-edit" });
7787
7933
  }, [postToParent2]);
7788
- const deselect = (0, import_react8.useCallback)(() => {
7934
+ const deselect = (0, import_react9.useCallback)(() => {
7789
7935
  selectedElRef.current = null;
7790
7936
  setReorderHrefKey(null);
7791
7937
  setReorderDragDisabled(false);
@@ -7799,7 +7945,7 @@ function OhhwellsBridge() {
7799
7945
  setToolbarVariant("none");
7800
7946
  }
7801
7947
  }, []);
7802
- const reselectNavigationItem = (0, import_react8.useCallback)((navAnchor) => {
7948
+ const reselectNavigationItem = (0, import_react9.useCallback)((navAnchor) => {
7803
7949
  selectedElRef.current = navAnchor;
7804
7950
  const { key, disabled } = getNavigationItemReorderState(navAnchor);
7805
7951
  setReorderHrefKey(key);
@@ -7809,7 +7955,7 @@ function OhhwellsBridge() {
7809
7955
  setToolbarShowEditLink(false);
7810
7956
  setActiveCommands(/* @__PURE__ */ new Set());
7811
7957
  }, []);
7812
- const commitNavigationTextEdit = (0, import_react8.useCallback)((navAnchor) => {
7958
+ const commitNavigationTextEdit = (0, import_react9.useCallback)((navAnchor) => {
7813
7959
  const el = activeElRef.current;
7814
7960
  if (!el) return;
7815
7961
  const key = el.dataset.ohwKey;
@@ -7835,7 +7981,7 @@ function OhhwellsBridge() {
7835
7981
  postToParent2({ type: "ow:exit-edit" });
7836
7982
  reselectNavigationItem(navAnchor);
7837
7983
  }, [postToParent2, reselectNavigationItem]);
7838
- const handleAddTopLevelNavItem = (0, import_react8.useCallback)(() => {
7984
+ const handleAddTopLevelNavItem = (0, import_react9.useCallback)(() => {
7839
7985
  const items = listNavbarItems();
7840
7986
  addNavAfterAnchorRef.current = items[items.length - 1] ?? null;
7841
7987
  deselectRef.current();
@@ -7847,17 +7993,17 @@ function OhhwellsBridge() {
7847
7993
  intent: "add-nav"
7848
7994
  });
7849
7995
  }, []);
7850
- const handleItemDragStart = (0, import_react8.useCallback)(() => {
7996
+ const handleItemDragStart = (0, import_react9.useCallback)(() => {
7851
7997
  siblingHintElRef.current = null;
7852
7998
  setSiblingHintRect(null);
7853
7999
  setIsItemDragging(true);
7854
8000
  }, []);
7855
- const handleItemDragEnd = (0, import_react8.useCallback)(() => {
8001
+ const handleItemDragEnd = (0, import_react9.useCallback)(() => {
7856
8002
  setIsItemDragging(false);
7857
8003
  }, []);
7858
8004
  reselectNavigationItemRef.current = reselectNavigationItem;
7859
8005
  commitNavigationTextEditRef.current = commitNavigationTextEdit;
7860
- const select = (0, import_react8.useCallback)((anchor) => {
8006
+ const select = (0, import_react9.useCallback)((anchor) => {
7861
8007
  if (!isNavigationItem(anchor)) return;
7862
8008
  if (activeElRef.current) deactivate();
7863
8009
  selectedElRef.current = anchor;
@@ -7877,7 +8023,7 @@ function OhhwellsBridge() {
7877
8023
  setToolbarShowEditLink(false);
7878
8024
  setActiveCommands(/* @__PURE__ */ new Set());
7879
8025
  }, [deactivate]);
7880
- const selectFrame = (0, import_react8.useCallback)((el) => {
8026
+ const selectFrame = (0, import_react9.useCallback)((el) => {
7881
8027
  if (!isNavigationContainer(el)) return;
7882
8028
  if (activeElRef.current) deactivate();
7883
8029
  selectedElRef.current = el;
@@ -7896,7 +8042,7 @@ function OhhwellsBridge() {
7896
8042
  setToolbarShowEditLink(false);
7897
8043
  setActiveCommands(/* @__PURE__ */ new Set());
7898
8044
  }, [deactivate]);
7899
- const activate = (0, import_react8.useCallback)((el, options) => {
8045
+ const activate = (0, import_react9.useCallback)((el, options) => {
7900
8046
  if (activeElRef.current === el) return;
7901
8047
  selectedElRef.current = null;
7902
8048
  deactivate();
@@ -7936,7 +8082,7 @@ function OhhwellsBridge() {
7936
8082
  selectRef.current = select;
7937
8083
  selectFrameRef.current = selectFrame;
7938
8084
  deselectRef.current = deselect;
7939
- (0, import_react8.useLayoutEffect)(() => {
8085
+ (0, import_react9.useLayoutEffect)(() => {
7940
8086
  if (!subdomain || isEditMode) {
7941
8087
  setFetchState("done");
7942
8088
  return;
@@ -7946,6 +8092,7 @@ function OhhwellsBridge() {
7946
8092
  for (const [key, val] of Object.entries(content)) {
7947
8093
  if (key === "__ohw_sections") continue;
7948
8094
  if (applyVideoSettingNode(key, val)) continue;
8095
+ if (applyCarouselNode(key, val)) continue;
7949
8096
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
7950
8097
  if (el.dataset.ohwEditable === "image") {
7951
8098
  const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
@@ -8005,7 +8152,7 @@ function OhhwellsBridge() {
8005
8152
  cancelled = true;
8006
8153
  };
8007
8154
  }, [subdomain, isEditMode]);
8008
- (0, import_react8.useEffect)(() => {
8155
+ (0, import_react9.useEffect)(() => {
8009
8156
  if (!subdomain || isEditMode) return;
8010
8157
  let debounceTimer = null;
8011
8158
  let observer = null;
@@ -8018,6 +8165,7 @@ function OhhwellsBridge() {
8018
8165
  for (const [key, val] of Object.entries(content)) {
8019
8166
  if (key === "__ohw_sections") continue;
8020
8167
  if (applyVideoSettingNode(key, val)) continue;
8168
+ if (applyCarouselNode(key, val)) continue;
8021
8169
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
8022
8170
  if (el.dataset.ohwEditable === "image") {
8023
8171
  const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
@@ -8054,16 +8202,16 @@ function OhhwellsBridge() {
8054
8202
  if (debounceTimer) clearTimeout(debounceTimer);
8055
8203
  };
8056
8204
  }, [subdomain, isEditMode, pathname]);
8057
- (0, import_react8.useLayoutEffect)(() => {
8205
+ (0, import_react9.useLayoutEffect)(() => {
8058
8206
  const el = document.getElementById("ohw-loader");
8059
8207
  if (!el) return;
8060
8208
  const visible = Boolean(subdomain) && fetchState !== "done";
8061
8209
  el.style.display = visible ? "flex" : "none";
8062
8210
  }, [subdomain, fetchState]);
8063
- (0, import_react8.useEffect)(() => {
8211
+ (0, import_react9.useEffect)(() => {
8064
8212
  postToParent2({ type: "ow:navigation", path: pathname });
8065
8213
  }, [pathname, postToParent2]);
8066
- (0, import_react8.useEffect)(() => {
8214
+ (0, import_react9.useEffect)(() => {
8067
8215
  if (!isEditMode) return;
8068
8216
  if (linkPopoverSessionRef.current?.intent === "add-nav") return;
8069
8217
  if (document.querySelector("[data-ohw-section-picker]")) return;
@@ -8071,7 +8219,7 @@ function OhhwellsBridge() {
8071
8219
  deselectRef.current();
8072
8220
  deactivateRef.current();
8073
8221
  }, [pathname, isEditMode]);
8074
- (0, import_react8.useEffect)(() => {
8222
+ (0, import_react9.useEffect)(() => {
8075
8223
  const contentForNav = () => {
8076
8224
  if (isEditMode) return editContentRef.current;
8077
8225
  if (!subdomain) return {};
@@ -8087,7 +8235,7 @@ function OhhwellsBridge() {
8087
8235
  observer.observe(nav, { childList: true, subtree: true });
8088
8236
  return () => observer.disconnect();
8089
8237
  }, [isEditMode, pathname, subdomain, fetchState]);
8090
- (0, import_react8.useEffect)(() => {
8238
+ (0, import_react9.useEffect)(() => {
8091
8239
  if (!isEditMode) return;
8092
8240
  const measure = () => {
8093
8241
  const h = document.body.scrollHeight;
@@ -8111,7 +8259,7 @@ function OhhwellsBridge() {
8111
8259
  window.removeEventListener("resize", handleResize);
8112
8260
  };
8113
8261
  }, [pathname, isEditMode, postToParent2]);
8114
- (0, import_react8.useEffect)(() => {
8262
+ (0, import_react9.useEffect)(() => {
8115
8263
  if (!subdomainFromQuery || isEditMode) return;
8116
8264
  const handleClick = (e) => {
8117
8265
  const anchor = e.target.closest("a");
@@ -8127,7 +8275,7 @@ function OhhwellsBridge() {
8127
8275
  document.addEventListener("click", handleClick, true);
8128
8276
  return () => document.removeEventListener("click", handleClick, true);
8129
8277
  }, [subdomainFromQuery, isEditMode, router]);
8130
- (0, import_react8.useEffect)(() => {
8278
+ (0, import_react9.useEffect)(() => {
8131
8279
  if (!isEditMode) {
8132
8280
  editStylesRef.current?.base.remove();
8133
8281
  editStylesRef.current?.forceHover.remove();
@@ -8956,6 +9104,7 @@ function OhhwellsBridge() {
8956
9104
  continue;
8957
9105
  }
8958
9106
  if (applyVideoSettingNode(key, val)) continue;
9107
+ if (applyCarouselNode(key, val)) continue;
8959
9108
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
8960
9109
  if (el.dataset.ohwEditable === "image") {
8961
9110
  const img = el instanceof HTMLImageElement ? el : el.querySelector("img");
@@ -9220,6 +9369,48 @@ function OhhwellsBridge() {
9220
9369
  if (e.data?.type !== "ow:canvas-height" || typeof e.data.height !== "number") return;
9221
9370
  document.documentElement.style.setProperty("--ohw-canvas-h", `${e.data.height}px`);
9222
9371
  };
9372
+ const handleCarouselChange = (e) => {
9373
+ if (e.data?.type !== "ow:carousel-change") return;
9374
+ const { key, images } = e.data;
9375
+ if (!key || !Array.isArray(images)) return;
9376
+ const text = JSON.stringify(images);
9377
+ applyCarouselValue(key, images);
9378
+ editContentRef.current = { ...editContentRef.current, [key]: text };
9379
+ postToParentRef.current({ type: "ow:change", nodes: [{ key, text }] });
9380
+ setCarouselHover(null);
9381
+ };
9382
+ const findCarouselAtPoint = (clientX, clientY) => {
9383
+ const containers = Array.from(document.querySelectorAll(`[${CAROUSEL_ATTR}]`));
9384
+ for (let i = containers.length - 1; i >= 0; i--) {
9385
+ const r2 = containers[i].getBoundingClientRect();
9386
+ if (clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom) {
9387
+ return containers[i];
9388
+ }
9389
+ }
9390
+ return null;
9391
+ };
9392
+ const isPointOverEditable = (scope, clientX, clientY) => {
9393
+ const editables = scope.querySelectorAll("[data-ohw-editable], [data-ohw-href-key]");
9394
+ for (const el of editables) {
9395
+ const r2 = el.getBoundingClientRect();
9396
+ if (clientX >= r2.left && clientX <= r2.right && clientY >= r2.top && clientY <= r2.bottom) return true;
9397
+ }
9398
+ return false;
9399
+ };
9400
+ const handleCarouselHover = (e) => {
9401
+ const container = findCarouselAtPoint(e.clientX, e.clientY);
9402
+ const scope = container?.closest("[data-ohw-section]") ?? container?.parentElement ?? null;
9403
+ if (!container || !scope || isPointOverEditable(scope, e.clientX, e.clientY)) {
9404
+ setCarouselHover((prev) => prev ? null : prev);
9405
+ return;
9406
+ }
9407
+ const key = container.getAttribute("data-ohw-key") ?? "";
9408
+ if (!key) return;
9409
+ const r2 = getVisibleRect(container);
9410
+ setCarouselHover(
9411
+ (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 } }
9412
+ );
9413
+ };
9223
9414
  const applyToolbarPos = (rect) => {
9224
9415
  const ps = parentScrollRef.current;
9225
9416
  const approxW = 330;
@@ -9328,6 +9519,7 @@ function OhhwellsBridge() {
9328
9519
  window.addEventListener("message", handleRemoveSchedulingSection);
9329
9520
  window.addEventListener("message", handleImageUrl);
9330
9521
  window.addEventListener("message", handleImageUploading);
9522
+ window.addEventListener("message", handleCarouselChange);
9331
9523
  window.addEventListener("message", handleCanvasHeight);
9332
9524
  window.addEventListener("message", handleParentScroll);
9333
9525
  window.addEventListener("message", handlePointerSync);
@@ -9345,6 +9537,7 @@ function OhhwellsBridge() {
9345
9537
  document.addEventListener("mouseover", handleMouseOver, true);
9346
9538
  document.addEventListener("mouseout", handleMouseOut, true);
9347
9539
  document.addEventListener("mousemove", handleMouseMove, true);
9540
+ document.addEventListener("mousemove", handleCarouselHover, true);
9348
9541
  document.addEventListener("mouseleave", handleDocMouseLeave);
9349
9542
  document.addEventListener("dragover", handleDragOver, true);
9350
9543
  document.addEventListener("dragleave", handleDragLeave, true);
@@ -9360,6 +9553,7 @@ function OhhwellsBridge() {
9360
9553
  document.removeEventListener("mouseover", handleMouseOver, true);
9361
9554
  document.removeEventListener("mouseout", handleMouseOut, true);
9362
9555
  document.removeEventListener("mousemove", handleMouseMove, true);
9556
+ document.removeEventListener("mousemove", handleCarouselHover, true);
9363
9557
  document.removeEventListener("mouseleave", handleDocMouseLeave);
9364
9558
  document.removeEventListener("dragover", handleDragOver, true);
9365
9559
  document.removeEventListener("dragleave", handleDragLeave, true);
@@ -9375,6 +9569,7 @@ function OhhwellsBridge() {
9375
9569
  window.removeEventListener("message", handleRemoveSchedulingSection);
9376
9570
  window.removeEventListener("message", handleImageUrl);
9377
9571
  window.removeEventListener("message", handleImageUploading);
9572
+ window.removeEventListener("message", handleCarouselChange);
9378
9573
  window.removeEventListener("message", handleCanvasHeight);
9379
9574
  window.removeEventListener("message", handleParentScroll);
9380
9575
  window.removeEventListener("resize", handleViewportResize);
@@ -9388,7 +9583,7 @@ function OhhwellsBridge() {
9388
9583
  if (imageShowTimerRef.current) clearTimeout(imageShowTimerRef.current);
9389
9584
  };
9390
9585
  }, [isEditMode, refreshStateRules]);
9391
- (0, import_react8.useEffect)(() => {
9586
+ (0, import_react9.useEffect)(() => {
9392
9587
  const handler = (e) => {
9393
9588
  if (e.data?.type !== "ow:request-schedule-config") return;
9394
9589
  const insertAfterVal = e.data.insertAfter;
@@ -9404,7 +9599,7 @@ function OhhwellsBridge() {
9404
9599
  window.addEventListener("message", handler);
9405
9600
  return () => window.removeEventListener("message", handler);
9406
9601
  }, [processConfigRequest]);
9407
- (0, import_react8.useEffect)(() => {
9602
+ (0, import_react9.useEffect)(() => {
9408
9603
  if (!isEditMode) return;
9409
9604
  document.querySelectorAll("[data-ohw-active-state]").forEach((el) => {
9410
9605
  el.removeAttribute("data-ohw-active-state");
@@ -9433,19 +9628,19 @@ function OhhwellsBridge() {
9433
9628
  clearTimeout(timer);
9434
9629
  };
9435
9630
  }, [pathname, isEditMode, refreshStateRules, postToParent2]);
9436
- (0, import_react8.useEffect)(() => {
9631
+ (0, import_react9.useEffect)(() => {
9437
9632
  scrollToHashSectionWhenReady();
9438
9633
  const onHashChange = () => scrollToHashSectionWhenReady();
9439
9634
  window.addEventListener("hashchange", onHashChange);
9440
9635
  return () => window.removeEventListener("hashchange", onHashChange);
9441
9636
  }, [pathname]);
9442
- const handleCommand = (0, import_react8.useCallback)((cmd) => {
9637
+ const handleCommand = (0, import_react9.useCallback)((cmd) => {
9443
9638
  document.execCommand(cmd, false);
9444
9639
  activeElRef.current?.focus();
9445
9640
  if (activeElRef.current) setToolbarRect(getEditMeasureEl(activeElRef.current).getBoundingClientRect());
9446
9641
  refreshActiveCommandsRef.current();
9447
9642
  }, []);
9448
- const handleStateChange = (0, import_react8.useCallback)((state) => {
9643
+ const handleStateChange = (0, import_react9.useCallback)((state) => {
9449
9644
  if (!activeStateElRef.current) return;
9450
9645
  const el = activeStateElRef.current;
9451
9646
  if (state === "Default") {
@@ -9458,11 +9653,11 @@ function OhhwellsBridge() {
9458
9653
  }
9459
9654
  setToggleState((prev) => prev ? { ...prev, activeState: state } : null);
9460
9655
  }, [deactivate]);
9461
- const closeLinkPopover = (0, import_react8.useCallback)(() => {
9656
+ const closeLinkPopover = (0, import_react9.useCallback)(() => {
9462
9657
  addNavAfterAnchorRef.current = null;
9463
9658
  setLinkPopover(null);
9464
9659
  }, []);
9465
- const openLinkPopoverForActive = (0, import_react8.useCallback)(() => {
9660
+ const openLinkPopoverForActive = (0, import_react9.useCallback)(() => {
9466
9661
  const hrefCtx = getHrefKeyFromElement(activeElRef.current);
9467
9662
  if (!hrefCtx) return;
9468
9663
  bumpLinkPopoverGrace();
@@ -9473,7 +9668,7 @@ function OhhwellsBridge() {
9473
9668
  });
9474
9669
  deactivate();
9475
9670
  }, [deactivate]);
9476
- const openLinkPopoverForSelected = (0, import_react8.useCallback)(() => {
9671
+ const openLinkPopoverForSelected = (0, import_react9.useCallback)(() => {
9477
9672
  const anchor = selectedElRef.current;
9478
9673
  if (!anchor) return;
9479
9674
  const key = anchor.getAttribute("data-ohw-href-key");
@@ -9486,7 +9681,7 @@ function OhhwellsBridge() {
9486
9681
  });
9487
9682
  deselect();
9488
9683
  }, [deselect]);
9489
- const handleLinkPopoverSubmit = (0, import_react8.useCallback)(
9684
+ const handleLinkPopoverSubmit = (0, import_react9.useCallback)(
9490
9685
  (target) => {
9491
9686
  const session = linkPopoverSessionRef.current;
9492
9687
  if (!session) return;
@@ -9545,13 +9740,19 @@ function OhhwellsBridge() {
9545
9740
  const showEditLink = toolbarShowEditLink;
9546
9741
  const currentSections = sectionsByPath[pathname] ?? [];
9547
9742
  linkPopoverOpenRef.current = linkPopover !== null;
9548
- const handleMediaReplace = (0, import_react8.useCallback)(
9743
+ const handleMediaReplace = (0, import_react9.useCallback)(
9549
9744
  (key) => {
9550
9745
  postToParent2({ type: "ow:image-pick", key, elementType: mediaHover?.elementType ?? "image" });
9551
9746
  },
9552
9747
  [postToParent2, mediaHover?.elementType]
9553
9748
  );
9554
- const handleMediaFadeOutComplete = (0, import_react8.useCallback)((key) => {
9749
+ const handleEditCarousel = (0, import_react9.useCallback)(
9750
+ (key) => {
9751
+ postToParent2({ type: "ow:carousel-open", key, images: readCarouselValue(key) });
9752
+ },
9753
+ [postToParent2]
9754
+ );
9755
+ const handleMediaFadeOutComplete = (0, import_react9.useCallback)((key) => {
9555
9756
  setUploadingRects((prev) => {
9556
9757
  if (!(key in prev)) return prev;
9557
9758
  const next = { ...prev };
@@ -9559,7 +9760,7 @@ function OhhwellsBridge() {
9559
9760
  return next;
9560
9761
  });
9561
9762
  }, []);
9562
- const handleVideoSettingsChange = (0, import_react8.useCallback)(
9763
+ const handleVideoSettingsChange = (0, import_react9.useCallback)(
9563
9764
  (key, settings) => {
9564
9765
  document.querySelectorAll(`[data-ohw-key="${key}"]`).forEach((el) => {
9565
9766
  const video = getVideoEl(el);
@@ -9582,9 +9783,9 @@ function OhhwellsBridge() {
9582
9783
  [postToParent2]
9583
9784
  );
9584
9785
  return bridgeRoot ? (0, import_react_dom3.createPortal)(
9585
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
9586
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
9587
- Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
9786
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
9787
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { ref: attachVisibleViewport, "data-ohw-visible-viewport": "", "aria-hidden": true }),
9788
+ Object.entries(uploadingRects).map(([key, { rect, fadingOut }]) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
9588
9789
  MediaOverlay,
9589
9790
  {
9590
9791
  hover: { key, rect, elementType: "image", isDragOver: false, hasTextOverlap: false },
@@ -9595,7 +9796,7 @@ function OhhwellsBridge() {
9595
9796
  },
9596
9797
  `uploading-${key}`
9597
9798
  )),
9598
- mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
9799
+ mediaHover && !(mediaHover.key in uploadingRects) && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
9599
9800
  MediaOverlay,
9600
9801
  {
9601
9802
  hover: mediaHover,
@@ -9604,17 +9805,18 @@ function OhhwellsBridge() {
9604
9805
  onVideoSettingsChange: handleVideoSettingsChange
9605
9806
  }
9606
9807
  ),
9607
- siblingHintRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
9608
- hoveredNavContainerRect && toolbarVariant !== "select-frame" && !linkPopover && !isItemDragging && !siblingHintRect && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
9609
- toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
9808
+ carouselHover && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(CarouselOverlay, { hover: carouselHover, onEdit: handleEditCarousel }),
9809
+ siblingHintRect && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ItemInteractionLayer, { rect: siblingHintRect, state: "sibling-hint" }),
9810
+ hoveredNavContainerRect && toolbarVariant !== "select-frame" && !linkPopover && !isItemDragging && !siblingHintRect && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ItemInteractionLayer, { rect: hoveredNavContainerRect, state: "hover" }),
9811
+ toolbarVariant === "select-frame" && toolbarRect && !linkPopover && !isItemDragging && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
9610
9812
  NavbarContainerChrome,
9611
9813
  {
9612
9814
  rect: toolbarRect,
9613
9815
  onAdd: handleAddTopLevelNavItem
9614
9816
  }
9615
9817
  ),
9616
- hoveredItemRect && !hoveredNavContainerRect && !siblingHintRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
9617
- toolbarRect && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
9818
+ hoveredItemRect && !hoveredNavContainerRect && !siblingHintRect && !isItemDragging && hoveredItemElRef.current !== selectedElRef.current && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(ItemInteractionLayer, { rect: hoveredItemRect, state: "hover" }),
9819
+ toolbarRect && (toolbarVariant === "link-action" || toolbarVariant === "select-frame") && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
9618
9820
  ItemInteractionLayer,
9619
9821
  {
9620
9822
  rect: toolbarRect,
@@ -9625,7 +9827,7 @@ function OhhwellsBridge() {
9625
9827
  dragHandleLabel: reorderHrefKey ? `Reorder ${reorderHrefKey}` : "Reorder item",
9626
9828
  onDragHandleDragStart: handleItemDragStart,
9627
9829
  onDragHandleDragEnd: handleItemDragEnd,
9628
- toolbar: toolbarVariant === "link-action" && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
9830
+ toolbar: toolbarVariant === "link-action" && !isItemDragging ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
9629
9831
  ItemActionToolbar,
9630
9832
  {
9631
9833
  onEditLink: openLinkPopoverForSelected,
@@ -9636,8 +9838,8 @@ function OhhwellsBridge() {
9636
9838
  ) : void 0
9637
9839
  }
9638
9840
  ),
9639
- toolbarRect && toolbarVariant === "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
9640
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
9841
+ toolbarRect && toolbarVariant === "rich-text" && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
9842
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
9641
9843
  EditGlowChrome,
9642
9844
  {
9643
9845
  rect: toolbarRect,
@@ -9646,7 +9848,7 @@ function OhhwellsBridge() {
9646
9848
  dragDisabled: reorderDragDisabled
9647
9849
  }
9648
9850
  ),
9649
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
9851
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
9650
9852
  FloatingToolbar,
9651
9853
  {
9652
9854
  rect: toolbarRect,
@@ -9659,7 +9861,7 @@ function OhhwellsBridge() {
9659
9861
  }
9660
9862
  )
9661
9863
  ] }),
9662
- maxBadge && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
9864
+ maxBadge && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
9663
9865
  "div",
9664
9866
  {
9665
9867
  "data-ohw-max-badge": "",
@@ -9685,7 +9887,7 @@ function OhhwellsBridge() {
9685
9887
  ]
9686
9888
  }
9687
9889
  ),
9688
- toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
9890
+ toggleState && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
9689
9891
  StateToggle,
9690
9892
  {
9691
9893
  rect: toggleState.rect,
@@ -9694,15 +9896,15 @@ function OhhwellsBridge() {
9694
9896
  onStateChange: handleStateChange
9695
9897
  }
9696
9898
  ),
9697
- sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
9899
+ sectionGap && !linkPopover && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
9698
9900
  "div",
9699
9901
  {
9700
9902
  "data-ohw-section-insert-line": "",
9701
9903
  className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
9702
9904
  style: { top: sectionGap.y, transform: "translateY(-50%)" },
9703
9905
  children: [
9704
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
9705
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
9906
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
9907
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
9706
9908
  Badge,
9707
9909
  {
9708
9910
  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",
@@ -9715,11 +9917,11 @@ function OhhwellsBridge() {
9715
9917
  children: "Add Section"
9716
9918
  }
9717
9919
  ),
9718
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
9920
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
9719
9921
  ]
9720
9922
  }
9721
9923
  ),
9722
- linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
9924
+ linkPopover && dialogPortalContainer ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
9723
9925
  LinkPopover,
9724
9926
  {
9725
9927
  panelRef: linkPopoverPanelRef,
@@ -9736,15 +9938,15 @@ function OhhwellsBridge() {
9736
9938
  },
9737
9939
  linkPopover.key
9738
9940
  ) : null,
9739
- sectionGap && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
9941
+ sectionGap && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
9740
9942
  "div",
9741
9943
  {
9742
9944
  "data-ohw-section-insert-line": "",
9743
9945
  className: "fixed left-0 w-full z-2147483646 flex items-center pointer-events-none",
9744
9946
  style: { top: sectionGap.y, transform: "translateY(-50%)" },
9745
9947
  children: [
9746
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
9747
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
9948
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } }),
9949
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
9748
9950
  Badge,
9749
9951
  {
9750
9952
  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",
@@ -9757,7 +9959,7 @@ function OhhwellsBridge() {
9757
9959
  children: "Add Section"
9758
9960
  }
9759
9961
  ),
9760
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
9962
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex-1 bg-primary", style: { height: 3 } })
9761
9963
  ]
9762
9964
  }
9763
9965
  )
@@ -9765,12 +9967,55 @@ function OhhwellsBridge() {
9765
9967
  bridgeRoot
9766
9968
  ) : null;
9767
9969
  }
9970
+
9971
+ // src/ui/drop-indicator.tsx
9972
+ var React10 = __toESM(require("react"), 1);
9973
+ var import_jsx_runtime25 = require("react/jsx-runtime");
9974
+ var dropIndicatorVariants = cva(
9975
+ "ov-gap-line pointer-events-none shrink-0 transition-opacity duration-150",
9976
+ {
9977
+ variants: {
9978
+ direction: {
9979
+ vertical: "h-6 w-[3px]",
9980
+ horizontal: "h-[3px] w-[200px]"
9981
+ },
9982
+ state: {
9983
+ default: "opacity-0",
9984
+ hover: "opacity-100",
9985
+ dragIdle: "opacity-40",
9986
+ dragActive: "opacity-100"
9987
+ }
9988
+ },
9989
+ defaultVariants: {
9990
+ direction: "vertical",
9991
+ state: "default"
9992
+ }
9993
+ }
9994
+ );
9995
+ var DropIndicator = React10.forwardRef(
9996
+ ({ className, direction, state, ...props }, ref) => {
9997
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
9998
+ "div",
9999
+ {
10000
+ ref,
10001
+ "data-slot": "drop-indicator",
10002
+ "data-direction": direction ?? "vertical",
10003
+ "data-state": state ?? "default",
10004
+ "aria-hidden": "true",
10005
+ className: cn(dropIndicatorVariants({ direction, state }), className),
10006
+ ...props
10007
+ }
10008
+ );
10009
+ }
10010
+ );
10011
+ DropIndicator.displayName = "DropIndicator";
9768
10012
  // Annotate the CommonJS export names for ESM import in node:
9769
10013
  0 && (module.exports = {
9770
10014
  CustomToolbar,
9771
10015
  CustomToolbarButton,
9772
10016
  CustomToolbarDivider,
9773
10017
  DragHandle,
10018
+ DropIndicator,
9774
10019
  ItemActionToolbar,
9775
10020
  ItemInteractionLayer,
9776
10021
  LinkEditorPanel,
@@ -9785,12 +10030,14 @@ function OhhwellsBridge() {
9785
10030
  TooltipProvider,
9786
10031
  TooltipTrigger,
9787
10032
  buildTarget,
10033
+ dropIndicatorVariants,
9788
10034
  filterAvailablePages,
9789
10035
  getEditModeInitialState,
9790
10036
  isEditSessionActive,
9791
10037
  isValidUrl,
9792
10038
  parseTarget,
9793
10039
  toggleVariants,
10040
+ useOhwCarousel,
9794
10041
  validateUrlInput
9795
10042
  });
9796
10043
  //# sourceMappingURL=index.cjs.map