docblocks-react-ui 0.1.1 → 0.3.0

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.mjs CHANGED
@@ -1,8 +1,8 @@
1
- import { $ as DropdownMenuContent, A as DEFAULT_EMBED_SANDBOX, B as Select, Bt as badgeVariants, Ct as CardAction, Dt as CardHeader, Et as CardFooter, F as newMutationContext, Ft as BookOpen, G as SelectScrollDownButton, Gt as PROTOCOL_VERSION, H as SelectGroup, Ht as AlertDescription, I as FilterBuilder, It as Button, J as SelectTrigger, Jt as BRIDGE_ERROR_CODES, K as SelectScrollUpButton, Kt as isDatabaseBridge, L as emptyFilter, Lt as buttonVariants, N as useDatabaseTable, Nt as Eye, O as EditorProvider, Ot as CardTitle, P as cellValueEqual, Q as DropdownMenuCheckboxItem, Qt as toBridgeError, R as filterIsComplete, Rt as BareSelect, St as Card, Tt as CardDescription, U as SelectItem, Ut as AlertTitle, V as SelectContent, Vt as Alert, W as SelectLabel, Wt as BASELINE_CAPABILITIES, X as Label, Xt as isBridgeError, Y as SelectValue, Yt as BridgeError, Z as DropdownMenu, Zt as isBridgeErrorCode, _t as PopoverHeader, an as Input, at as DropdownMenuRadioItem, bn as blobSubtypeOf, cn as useMeta, ct as DropdownMenuSub, dn as useSelectionView, dt as DropdownMenuTrigger, en as conditionMatches, et as DropdownMenuGroup, fn as useText, ft as Separator, g as markToggleAction, gn as renderRuns, gt as PopoverDescription, ht as PopoverContent, in as ScrollArea, it as DropdownMenuRadioGroup, jt as Pen, k as useEditorContext, l as SHAPE_FONT_OPTIONS, ln as usePresence, lt as DropdownMenuSubContent, mt as PopoverAnchor, nn as TEXT_TYPES, nt as DropdownMenuLabel, on as useBlock, ot as DropdownMenuSeparator, p as FORMAT_PALETTE, pt as Popover, q as SelectSeparator, qt as validateProtocolDescriptor, rn as columnAnnotation, rt as DropdownMenuPortal, sn as useDoc, st as DropdownMenuShortcut, t as Editor, tn as parseCellValue, tt as DropdownMenuItem, u as SHAPE_FONT_STACKS, un as useSelection, ut as DropdownMenuSubTrigger, vt as PopoverTitle, wt as CardContent, xn as createMemoryBlobStore, xt as Checkbox, yt as PopoverTrigger, z as SegmentSelector, zt as Badge } from "./Editor-CiJY5R4v.mjs";
1
+ import { $ as PopoverHeader, A as SelectTrigger, At as isBridgeErrorCode, B as DropdownMenuRadioGroup, Bt as useMeta, C as SelectContent, Ct as BASELINE_CAPABILITIES, D as SelectScrollDownButton, Dt as BRIDGE_ERROR_CODES, E as SelectLabel, Et as validateProtocolDescriptor, F as DropdownMenuContent, Ft as columnAnnotation, G as DropdownMenuSubContent, Gt as useText, H as DropdownMenuSeparator, Ht as usePresenceSharing, I as DropdownMenuGroup, It as ScrollArea, J as Separator, Jt as blobSubtypeOf, K as DropdownMenuSubTrigger, L as DropdownMenuItem, Lt as Input, M as Label, Mt as conditionMatches, N as DropdownMenu, Nt as parseCellValue, O as SelectScrollUpButton, Ot as BridgeError, P as DropdownMenuCheckboxItem, Pt as TEXT_TYPES, Q as PopoverDescription, R as DropdownMenuLabel, Rt as useBlock, S as Select, St as AlertTitle, T as SelectItem, Tt as isDatabaseBridge, U as DropdownMenuShortcut, Ut as useSelection, V as DropdownMenuRadioItem, Vt as usePresence, W as DropdownMenuSub, Wt as useSelectionView, X as PopoverAnchor, Y as Popover, Yt as createMemoryBlobStore, Z as PopoverContent, _ as FilterBuilder, _t as BareSelect, a as SHAPE_FONT_STACKS, at as CardAction, b as Skeleton, bt as Alert, ct as CardFooter, d as useEditorContext, dt as Pen, et as PopoverTitle, f as DEFAULT_EMBED_SANDBOX, ft as Eye, g as newMutationContext, gt as buttonVariants, h as cellValueEqual, ht as Button, i as SHAPE_FONT_OPTIONS, it as Card, j as SelectValue, jt as toBridgeError, k as SelectSeparator, kt as isBridgeError, l as markToggleAction, lt as CardHeader, m as useDatabaseTable, mt as BookOpen, nt as DocblocksI18nProvider, o as FORMAT_PALETTE, ot as CardContent, p as GridBody, q as DropdownMenuTrigger, qt as renderRuns, rt as Checkbox, st as CardDescription, t as Editor, tt as PopoverTrigger, u as EditorProvider, ut as CardTitle, v as emptyFilter, vt as Badge, w as SelectGroup, wt as PROTOCOL_VERSION, x as SegmentSelector, xt as AlertDescription, y as filterIsComplete, yt as badgeVariants, z as DropdownMenuPortal, zt as useDoc } from "./Editor-BvKqUGXH.mjs";
2
2
  import { c as cn, o as preventDefault } from "./constants-D4FTL0ph.mjs";
3
- import { t as Skeleton } from "./Skeleton-D922Ths5.mjs";
4
- import { useEffect, useRef, useState } from "react";
3
+ import { useCallback, useEffect, useRef, useState } from "react";
5
4
  import { jsx, jsxs } from "react/jsx-runtime";
5
+ import { useTranslation } from "react-i18next";
6
6
  import { cva } from "class-variance-authority";
7
7
  import * as TabsPrimitive from "@radix-ui/react-tabs";
8
8
  import * as TooltipPrimitive from "@radix-ui/react-tooltip";
@@ -211,14 +211,20 @@ const AVATAR_EMOJI = [
211
211
  * content is portaled outside the editor root, where the `--docblocks-*`
212
212
  * tokens are not mapped).
213
213
  */
214
- function EmojiPicker({ selected, onPick, onClear }) {
214
+ /** The picker's i18n scope: the package's instance stands the provider's seat
215
+ * over the picker (it stands also outside the editor's scope). */
216
+ function EmojiPicker(props) {
217
+ return /* @__PURE__ */ jsx(DocblocksI18nProvider, { children: /* @__PURE__ */ jsx(EmojiPickerInner, { ...props }) });
218
+ }
219
+ function EmojiPickerInner({ selected, onPick, onClear }) {
220
+ const { t } = useTranslation("editor");
215
221
  const pickEmoji = (emoji) => () => onPick(emoji);
216
222
  return /* @__PURE__ */ jsxs("div", {
217
223
  "data-slot": "docblocks/emoji-picker",
218
224
  className: "flex w-52 flex-col gap-2",
219
225
  children: [/* @__PURE__ */ jsx("div", {
220
226
  role: "group",
221
- "aria-label": "Avatar emoji",
227
+ "aria-label": t("shared.emojiPickerGroup"),
222
228
  className: "grid grid-cols-6 gap-1",
223
229
  children: AVATAR_EMOJI.map(({ emoji, label }) => {
224
230
  const isSelected = selected === emoji;
@@ -246,7 +252,7 @@ function EmojiPicker({ selected, onPick, onClear }) {
246
252
  "data-slot": "docblocks/emoji-picker-clear",
247
253
  className: "\n -mx-1 h-auto px-2 py-1 text-left text-xs font-normal text-muted-foreground transition-colors\n focus-visible:ring-0 focus-visible:outline-1 focus-visible:outline-ring\n ",
248
254
  onClick: onClear,
249
- children: "Remove avatar"
255
+ children: t("shared.removeAvatar")
250
256
  })]
251
257
  });
252
258
  }
@@ -374,6 +380,101 @@ function TooltipContent({ className, sideOffset = 0, children, ...props }) {
374
380
  }) });
375
381
  }
376
382
  //#endregion
383
+ //#region src/database/standalone/DatabaseTable.tsx
384
+ /** The stable absent-seed's stand (the `view` prop's absent stand). */
385
+ const EMPTY_VIEW = {};
386
+ /**
387
+ * The standalone's database table: the live grid over the bridge's table
388
+ * id — the same `useDatabaseTable`'s data stand as the document block
389
+ * (the schema + the rows + the live events + the optimistic cell's layer),
390
+ * rendered outside any document (the consumer's own page / panel). The
391
+ * view's settings stand the internal's state (seeded from the `view`
392
+ * prop) + the consumer's persistence over the `onViewChange`'s patch
393
+ * (one patch per change, as the block's `updateBlock` stand). The i18n's
394
+ * scope stands self-contained (the package's instance — the same's stand
395
+ * as the consumer-placed components).
396
+ */
397
+ function DatabaseTable({ bridge, tableId, readOnly = false, view, onViewChange }) {
398
+ const [viewState, setViewState] = useState(view ?? EMPTY_VIEW);
399
+ const viewRef = useRef(viewState);
400
+ viewRef.current = viewState;
401
+ const handleViewChange = useCallback((patch) => {
402
+ const typed = patch;
403
+ setViewState((current) => ({
404
+ ...current,
405
+ ...typed
406
+ }));
407
+ if (onViewChange !== void 0) onViewChange(typed);
408
+ }, [onViewChange]);
409
+ return /* @__PURE__ */ jsx(DocblocksI18nProvider, { children: /* @__PURE__ */ jsx(GridBody, {
410
+ bridge,
411
+ tableId,
412
+ filter: viewState.filter,
413
+ columnOrder: viewState.columnOrder,
414
+ hiddenColumns: viewState.hiddenColumns,
415
+ columnWidths: viewState.columnWidths,
416
+ onViewChange: handleViewChange,
417
+ readColumnOrder: () => viewRef.current.columnOrder,
418
+ readOnly
419
+ }) });
420
+ }
421
+ //#endregion
422
+ //#region src/database/standalone/use-table-list.ts
423
+ /**
424
+ * The table catalog's hook (the standalone's stand): the consumer's
425
+ * `DatabaseBridge`'s catalog read (`listTables` — the system tables stand
426
+ * absent) + the `createTable` / `renameTable` mutations (the fresh's
427
+ * `operationId` per op over `newMutationContext`). The catalog's truth
428
+ * stands in the bridge — the hook's state is the read projection,
429
+ * re-read over the own's successful mutations (the auto's stand) + the
430
+ * manual's `refresh` (the contract's catalog stands no push — the
431
+ * per-table's events stand over the `useDatabaseTable`'s subscription).
432
+ * The create / rename's failures stand their promises' rejects (the
433
+ * `BridgeError` stand) — the `error` state is the catalog read's own.
434
+ */
435
+ function useTableList(bridge) {
436
+ const [tables, setTables] = useState(null);
437
+ const [loading, setLoading] = useState(true);
438
+ const [error, setError] = useState(null);
439
+ const bridgeRef = useRef(bridge);
440
+ bridgeRef.current = bridge;
441
+ const readSeq = useRef(0);
442
+ const refresh = useCallback(async () => {
443
+ const seq = ++readSeq.current;
444
+ setLoading(true);
445
+ try {
446
+ const list = await bridgeRef.current.listTables();
447
+ if (seq !== readSeq.current) return;
448
+ setTables(list);
449
+ setError(null);
450
+ } catch (error) {
451
+ if (seq !== readSeq.current) return;
452
+ setTables(null);
453
+ setError(toBridgeError(error));
454
+ } finally {
455
+ if (seq === readSeq.current) setLoading(false);
456
+ }
457
+ }, []);
458
+ useEffect(() => {
459
+ refresh();
460
+ }, [refresh]);
461
+ return {
462
+ tables,
463
+ loading,
464
+ error,
465
+ refresh,
466
+ create: useCallback(async (name) => {
467
+ const receipt = await bridgeRef.current.createTable({ name }, newMutationContext());
468
+ await refresh();
469
+ return receipt.result;
470
+ }, [refresh]),
471
+ rename: useCallback(async (tableId, name) => {
472
+ await bridgeRef.current.renameTable(tableId, { name }, newMutationContext());
473
+ await refresh();
474
+ }, [refresh])
475
+ };
476
+ }
477
+ //#endregion
377
478
  //#region src/DocHeader.tsx
378
479
  /**
379
480
  * The document's header panel — a consumer-placed component (outside the
@@ -436,7 +537,16 @@ function InlineEditInput({ initial, ariaLabel, slot, className, onCommit, onCanc
436
537
  onKeyDown: onInputKeyDown
437
538
  });
438
539
  }
439
- function DocHeader({ doc, view, onViewChange, accessLevel = "editor", mode = "edit", onModeChange, publishedDoc }) {
540
+ /** The header's i18n scope: the package's instance stands the provider's seat
541
+ * over the panel (the consumer places the header outside the editor — the
542
+ * editor's own scope never reaches it). A consumer-wrapped subtree stands
543
+ * the same instance nested — the provider is a plain context, the render
544
+ * is unchanged. */
545
+ function DocHeader(props) {
546
+ return /* @__PURE__ */ jsx(DocblocksI18nProvider, { children: /* @__PURE__ */ jsx(DocHeaderInner, { ...props }) });
547
+ }
548
+ function DocHeaderInner({ doc, view, onViewChange, accessLevel = "editor", mode = "edit", onModeChange, publishedDoc }) {
549
+ const { t } = useTranslation("editor");
440
550
  const effectiveMode = accessLevel === "viewer" ? "published" : mode;
441
551
  const viewMode = effectiveMode !== "edit";
442
552
  const snapshot = effectiveMode === "published" ? accessLevel === "viewer" ? doc ?? null : publishedDoc ?? null : null;
@@ -490,16 +600,16 @@ function DocHeader({ doc, view, onViewChange, accessLevel = "editor", mode = "ed
490
600
  /* @__PURE__ */ jsx(SegmentSelector, {
491
601
  options: [{
492
602
  value: "page",
493
- label: "Page view",
603
+ label: t("docHeader.pageView"),
494
604
  icon: /* @__PURE__ */ jsx(SquareText, { className: "size-4" })
495
605
  }, {
496
606
  value: "canvas",
497
- label: "Canvas view",
607
+ label: t("docHeader.canvasView"),
498
608
  icon: /* @__PURE__ */ jsx(Network, { className: "size-4" })
499
609
  }],
500
610
  value: view,
501
611
  onChange: switchView,
502
- ariaLabel: "Document view",
612
+ ariaLabel: t("docHeader.documentViewAria"),
503
613
  slot: "docblocks/doc-header-view",
504
614
  pillSlot: "docblocks/doc-header-view-pill",
505
615
  buttonAttrName: "doc-header-view-button"
@@ -508,31 +618,31 @@ function DocHeader({ doc, view, onViewChange, accessLevel = "editor", mode = "ed
508
618
  options: [
509
619
  {
510
620
  value: "edit",
511
- label: "Edit mode",
621
+ label: t("docHeader.editMode"),
512
622
  icon: /* @__PURE__ */ jsx(Pen, { className: "size-4" })
513
623
  },
514
624
  {
515
625
  value: "view",
516
- label: "View mode",
626
+ label: t("docHeader.viewMode"),
517
627
  icon: /* @__PURE__ */ jsx(Eye, { className: "size-4" })
518
628
  },
519
629
  {
520
630
  value: "published",
521
- label: "Published",
631
+ label: t("docHeader.published"),
522
632
  icon: /* @__PURE__ */ jsx(BookOpen, { className: "size-4" }),
523
633
  disabled: publishedDoc === null || publishedDoc === void 0
524
634
  }
525
635
  ],
526
636
  value: effectiveMode,
527
637
  onChange: switchMode,
528
- ariaLabel: "Document mode",
638
+ ariaLabel: t("docHeader.documentModeAria"),
529
639
  slot: "docblocks/doc-header-mode",
530
640
  pillSlot: "docblocks/doc-header-mode-pill",
531
641
  buttonAttrName: "doc-header-mode-button"
532
642
  }) : null,
533
643
  viewMode ? /* @__PURE__ */ jsx("span", {
534
644
  "data-slot": "docblocks/doc-header-avatar",
535
- "aria-label": "Document avatar",
645
+ "aria-label": t("docHeader.documentAvatarAria"),
536
646
  className: cn("flex size-8 shrink-0 items-center justify-center overflow-hidden rounded-full text-base font-normal", displayMeta.avatar ? "bg-muted" : "border border-dashed border-input text-muted-foreground"),
537
647
  children: displayMeta.avatar ?? ""
538
648
  }) : /* @__PURE__ */ jsxs(Popover, {
@@ -545,8 +655,8 @@ function DocHeader({ doc, view, onViewChange, accessLevel = "editor", mode = "ed
545
655
  variant: "ghost",
546
656
  size: "icon",
547
657
  "data-slot": "docblocks/doc-header-avatar",
548
- "aria-label": "Edit the document avatar",
549
- title: "Edit the avatar",
658
+ "aria-label": t("docHeader.editAvatarAria"),
659
+ title: t("docHeader.editAvatar"),
550
660
  className: cn("size-8 shrink-0 overflow-hidden rounded-full text-base font-normal", liveMeta.avatar ? "bg-muted" : "border border-dashed border-input text-muted-foreground"),
551
661
  children: liveMeta.avatar ? liveMeta.avatar : "+"
552
662
  })
@@ -564,30 +674,30 @@ function DocHeader({ doc, view, onViewChange, accessLevel = "editor", mode = "ed
564
674
  }),
565
675
  titleEditing && !viewMode ? /* @__PURE__ */ jsx(InlineEditInput, {
566
676
  initial: liveMeta.title,
567
- ariaLabel: "Document title",
677
+ ariaLabel: t("docHeader.documentTitleAria"),
568
678
  slot: "docblocks/doc-header-title-edit",
569
679
  className: "\n h-auto min-w-0 flex-1 border-0 bg-background p-0 text-lg font-semibold shadow-none\n focus-visible:ring-0\n dark:bg-transparent\n ",
570
680
  onCommit: commitTitleEdit,
571
681
  onCancel: cancelTitleEdit
572
682
  }) : viewMode ? /* @__PURE__ */ jsx("span", {
573
683
  "data-slot": "docblocks/doc-header-title",
574
- "aria-label": "Document title",
684
+ "aria-label": t("docHeader.documentTitleAria"),
575
685
  className: "min-w-0 flex-1 truncate text-left text-lg font-semibold",
576
686
  children: displayMeta.title || /* @__PURE__ */ jsx("span", {
577
687
  className: "text-muted-foreground",
578
- children: "Untitled"
688
+ children: t("common:untitled")
579
689
  })
580
690
  }) : /* @__PURE__ */ jsx(Button, {
581
691
  type: "button",
582
692
  variant: "ghost",
583
693
  "data-slot": "docblocks/doc-header-title",
584
- "aria-label": "Edit the document title",
585
- title: "Edit the title",
694
+ "aria-label": t("docHeader.editTitleAria"),
695
+ title: t("docHeader.editTitle"),
586
696
  onClick: beginTitleEdit,
587
697
  className: "h-auto min-w-0 flex-1 truncate text-left text-lg font-semibold",
588
698
  children: liveMeta.title || /* @__PURE__ */ jsx("span", {
589
699
  className: "text-muted-foreground",
590
- children: "Untitled"
700
+ children: t("common:untitled")
591
701
  })
592
702
  })
593
703
  ]
@@ -638,4 +748,4 @@ const UI_FONT_STACK = "'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif
638
748
  */
639
749
  const MONO_FONT_STACK = "ui-monospace, SFMono-Regular, Menlo, Consolas, monospace";
640
750
  //#endregion
641
- export { Alert, AlertDescription, AlertTitle, BASELINE_CAPABILITIES, BRIDGE_ERROR_CODES, Badge, BareSelect, BridgeError, Button, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, DEFAULT_EMBED_SANDBOX, DocHeader, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Editor, EditorProvider, FORMAT_PALETTE, FilterBuilder, Input, Label, MONO_FONT_STACK, PROTOCOL_VERSION, Popover, PopoverAnchor, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger, SHAPE_FONT_OPTIONS, SHAPE_FONT_STACKS, ScrollArea, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Skeleton, TEXT_TYPES, Tabs, TabsContent, TabsList, TabsTrigger, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, UI_FONT_ID, UI_FONT_STACK, badgeVariants, blobSubtypeOf, buttonVariants, cellValueEqual, cn, columnAnnotation, conditionMatches, createMemoryBlobStore, emptyFilter, filterIsComplete, isBridgeError, isBridgeErrorCode, isDatabaseBridge, markToggleAction, newMutationContext, parseCellValue, renderRuns, toBridgeError, useBlock, useDatabaseTable, useDoc, useEditorContext, useMeta, usePresence, useSelection, useSelectionView, useText, validateProtocolDescriptor };
751
+ export { Alert, AlertDescription, AlertTitle, BASELINE_CAPABILITIES, BRIDGE_ERROR_CODES, Badge, BareSelect, BridgeError, Button, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, DEFAULT_EMBED_SANDBOX, DatabaseTable, DocHeader, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Editor, EditorProvider, FORMAT_PALETTE, FilterBuilder, Input, Label, MONO_FONT_STACK, PROTOCOL_VERSION, Popover, PopoverAnchor, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger, SHAPE_FONT_OPTIONS, SHAPE_FONT_STACKS, ScrollArea, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Skeleton, TEXT_TYPES, Tabs, TabsContent, TabsList, TabsTrigger, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, UI_FONT_ID, UI_FONT_STACK, badgeVariants, blobSubtypeOf, buttonVariants, cellValueEqual, cn, columnAnnotation, conditionMatches, createMemoryBlobStore, emptyFilter, filterIsComplete, isBridgeError, isBridgeErrorCode, isDatabaseBridge, markToggleAction, newMutationContext, parseCellValue, renderRuns, toBridgeError, useBlock, useDatabaseTable, useDoc, useEditorContext, useMeta, usePresence, usePresenceSharing, useSelection, useSelectionView, useTableList, useText, validateProtocolDescriptor };
@@ -1,9 +1,9 @@
1
- import { Ht as AlertDescription, Nt as Eye, Pt as CodeXml, Ut as AlertTitle, Vt as Alert, c as CodeHeader, h as textOf, hn as INLINE_CODE_CLASS, k as useEditorContext, m as TextBlock, s as childrenSlot, z as SegmentSelector } from "../Editor-CiJY5R4v.mjs";
1
+ import { Kt as INLINE_CODE_CLASS, St as AlertTitle, b as Skeleton, bt as Alert, c as textOf, d as useEditorContext, ft as Eye, n as childrenSlot, pt as CodeXml, r as CodeHeader, s as TextBlock, x as SegmentSelector, xt as AlertDescription } from "../Editor-BvKqUGXH.mjs";
2
2
  import { n as TriangleAlert } from "../constants-D4FTL0ph.mjs";
3
3
  import { t as LoaderCircle } from "../LoaderCircle-AGVFE4IP.mjs";
4
- import { t as Skeleton } from "../Skeleton-D922Ths5.mjs";
5
4
  import { useEffect, useRef, useState } from "react";
6
5
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
6
+ import { useTranslation } from "react-i18next";
7
7
  import mermaid from "mermaid";
8
8
  //#region src/mermaid/mermaid-config.ts
9
9
  /** The mermaid renderer's config stand (the v1 security + behavior stand —
@@ -44,7 +44,7 @@ function safeId(id) {
44
44
  return id.replace(/[^a-zA-Z0-9_-]/g, "");
45
45
  }
46
46
  //#endregion
47
- //#region src/mermaid/useContainerTheme.ts
47
+ //#region src/mermaid/use-container-theme.ts
48
48
  /** The editor's theme for one ref'd element, reactive to a theme flip:
49
49
  * a single MutationObserver watches the `class` attribute of the
50
50
  * element's ancestor chain (collected on mount — the preview's branch
@@ -93,6 +93,7 @@ function useContainerTheme(ref) {
93
93
  /** A unique mermaid render id per attempt (mermaid requires one per render). */
94
94
  let renderSeq = 0;
95
95
  function MermaidDiagram({ id, text }) {
96
+ const { t } = useTranslation("blocks");
96
97
  const containerRef = useRef(null);
97
98
  const theme = useContainerTheme(containerRef);
98
99
  const [state, setState] = useState({
@@ -165,7 +166,7 @@ function MermaidDiagram({ id, text }) {
165
166
  className: "absolute inset-0 flex items-center justify-center gap-2",
166
167
  children: [/* @__PURE__ */ jsx(LoaderCircle, { className: "size-4 animate-spin" }), /* @__PURE__ */ jsx("span", {
167
168
  "data-slot": "docblocks/mermaid-loading",
168
- children: "rendering…"
169
+ children: t("code.rendering")
169
170
  })]
170
171
  })]
171
172
  });
@@ -1,4 +1,4 @@
1
- import { f as PdfPreviewProps } from "../index-D6_ysSmQ.mjs";
1
+ import { f as PdfPreviewProps } from "../index-DG0lJy_t.mjs";
2
2
  //#region src/pdf/PdfFirstPage.d.ts
3
3
  declare function PdfFirstPage({ id, url, name }: PdfPreviewProps): import("react").JSX.Element;
4
4
  //#endregion
@@ -2,6 +2,7 @@ import { a as isSafeDownloadHref, c as cn, n as TriangleAlert, t as isEmbeddable
2
2
  import { t as LoaderCircle } from "../LoaderCircle-AGVFE4IP.mjs";
3
3
  import { useEffect, useRef, useState } from "react";
4
4
  import { jsx, jsxs } from "react/jsx-runtime";
5
+ import { useTranslation } from "react-i18next";
5
6
  import { GlobalWorkerOptions, RenderingCancelledException, getDocument } from "pdfjs-dist";
6
7
  //#region src/pdf/pdf-worker.ts
7
8
  /** The pdfjs-dist worker wiring (the side-effect): the worker file is
@@ -22,6 +23,9 @@ import { GlobalWorkerOptions, RenderingCancelledException, getDocument } from "p
22
23
  const WORKER_URL = new URL(`./pdf.worker.min.mjs`, import.meta.url);
23
24
  GlobalWorkerOptions.workerSrc = WORKER_URL.toString();
24
25
  const WASM_URL = new URL("./", WORKER_URL).toString();
26
+ if (typeof window !== "undefined") fetch(WORKER_URL, { method: "HEAD" }).catch(() => {
27
+ console.warn("docblocks: the pdf worker's asset is unreachable over this entry — the pdf preview stands the native viewer's fallback (the worker's load fails). The dist/pdf/ directory must stand served as static assets next to the subpath's entry.");
28
+ });
25
29
  //#endregion
26
30
  //#region src/pdf/PdfFirstPage.tsx
27
31
  /** The first-page preview of one `pdf`-subtype image block: fetch the
@@ -33,6 +37,7 @@ const WASM_URL = new URL("./", WORKER_URL).toString();
33
37
  * so a torn-down preview leaves no network request or pdf.js worker
34
38
  * behind. */
35
39
  function PdfFirstPage({ id, url, name }) {
40
+ const { t } = useTranslation("blocks");
36
41
  const canvasRef = useRef(null);
37
42
  const loadingTaskRef = useRef(null);
38
43
  const renderTaskRef = useRef(null);
@@ -111,13 +116,9 @@ function PdfFirstPage({ id, url, name }) {
111
116
  children: [/* @__PURE__ */ jsxs("div", {
112
117
  "data-slot": "docblocks/image-pdf-error",
113
118
  className: "\n mb-2 flex items-center gap-2 rounded-(--docblocks-radius) border-(length:--docblocks-table-border-width)\n border-(--docblocks-table-border-color) bg-(--muted) px-3 py-2 text-sm text-(--muted-foreground)\n ",
114
- children: [/* @__PURE__ */ jsx(TriangleAlert, { className: "size-4 shrink-0" }), /* @__PURE__ */ jsxs("span", {
119
+ children: [/* @__PURE__ */ jsx(TriangleAlert, { className: "size-4 shrink-0" }), /* @__PURE__ */ jsx("span", {
115
120
  className: "min-w-0 flex-1 truncate",
116
- children: [
117
- "PDF preview unavailable (",
118
- error,
119
- "). Showing the built-in viewer."
120
- ]
121
+ children: t("code.pdfPreviewUnavailable", { error })
121
122
  })]
122
123
  }), isEmbeddablePdfUrl(url) ? /* @__PURE__ */ jsx("iframe", {
123
124
  "data-slot": "docblocks/image-pdf",
@@ -155,7 +156,7 @@ function PdfFirstPage({ id, url, name }) {
155
156
  className: "flex h-48 w-full items-center justify-center gap-2 text-sm text-(--muted-foreground)",
156
157
  children: [/* @__PURE__ */ jsx(LoaderCircle, { className: "size-4 animate-spin" }), /* @__PURE__ */ jsx("span", {
157
158
  "data-slot": "docblocks/image-pdf-loading",
158
- children: "loading preview…"
159
+ children: t("code.pdfLoading")
159
160
  })]
160
161
  })]
161
162
  });
package/dist/styles.css CHANGED
@@ -3673,6 +3673,20 @@
3673
3673
  overscroll-behavior: contain;
3674
3674
  }
3675
3675
 
3676
+ /*
3677
+ * The editor root's focus-ring stand: the root is a focus PARK (the
3678
+ * gestures' contract — the drag's release and the gutter's delete park
3679
+ * the focus there so the keyboard's input stays scoped over the editor).
3680
+ * It is reached programmatically only (tabIndex -1 — no Tab focus), so
3681
+ * the browser's default focus ring would stand the visible ring over the
3682
+ * whole document after a drag's release. The ring is suppressed; the
3683
+ * focus itself stays (the keyboard's scoping needs it), and the
3684
+ * individual controls keep their own focus styles.
3685
+ */
3686
+ [data-slot="docblocks/editor"]:focus {
3687
+ outline: none;
3688
+ }
3689
+
3676
3690
  /*
3677
3691
  * The read-only stand (view / published modes): the editor's content is
3678
3692
  * read-only — the text selection stands no stand (the native range's
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docblocks-react-ui",
3
- "version": "0.1.1",
3
+ "version": "0.3.0",
4
4
  "description": "React rendering + editing layer for docblocks: hooks, block renderers, caret/selection, keyboard, clipboard.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -27,10 +27,6 @@
27
27
  "types": "./dist/pdf/index.d.mts",
28
28
  "import": "./dist/pdf/index.mjs"
29
29
  },
30
- "./motion": {
31
- "types": "./dist/motion/index.d.mts",
32
- "import": "./dist/motion/index.mjs"
33
- },
34
30
  "./styles.css": "./dist/styles.css",
35
31
  "./theme.css": "./theme.css"
36
32
  },
@@ -38,24 +34,13 @@
38
34
  "access": "public"
39
35
  },
40
36
  "peerDependencies": {
41
- "docblocks-core": "*",
37
+ "docblocks-core": "^0.1.3",
42
38
  "framer-motion": "^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0",
43
39
  "mermaid": "^12.0.0",
44
40
  "pdfjs-dist": "^6.0.0",
45
41
  "react": "^19.0.0",
46
42
  "react-dom": "^19.0.0"
47
43
  },
48
- "peerDependenciesMeta": {
49
- "framer-motion": {
50
- "optional": true
51
- },
52
- "mermaid": {
53
- "optional": true
54
- },
55
- "pdfjs-dist": {
56
- "optional": true
57
- }
58
- },
59
44
  "dependencies": {
60
45
  "@radix-ui/react-checkbox": "^1.3.11",
61
46
  "@radix-ui/react-dropdown-menu": "^2.1.24",
@@ -69,7 +54,9 @@
69
54
  "clsx": "^2.1.1",
70
55
  "date-fns": "^4.4.0",
71
56
  "highlight.js": "^11.12.0",
57
+ "i18next": "^27.0.1",
72
58
  "react-day-picker": "^10.0.2",
59
+ "react-i18next": "^18.0.1",
73
60
  "tailwind-merge": "^3.7.0",
74
61
  "zustand": "^5.0.15"
75
62
  },
@@ -1,32 +0,0 @@
1
- //#region src/Editor.d.ts
2
- /**
3
- * The document's view mode: the page flow (the root's children in reading
4
- * order) or the canvas (the page as a miniature rectangle plus the surface
5
- * elements on one canvas). View state — switching writes nothing to the
6
- * data (like the selection).
7
- */
8
- type EditorView = "page" | "canvas";
9
- interface EditorProps {
10
- view?: EditorView;
11
- /** The format toolbar's color palette (the default six colors). */
12
- formatPalette?: readonly string[];
13
- }
14
- /**
15
- * Renders the document's entry list in reading order (the document root's
16
- * children, or a single subtree block when the provider got a
17
- * `rootBlockId`). The root is the editor's focus/keyboard scope: the
18
- * undo/redo hotkeys only fire for keys targeted inside it. The root block
19
- * context is provided for every entry: the entry list's siblings, and the
20
- * entry root's sequence container as the gestures' command parent (a
21
- * subtree entry root is a page block — structurally childless, so its
22
- * commands target the container of its sequence, not itself).
23
- *
24
- * The `view` prop selects the rendering: "page" (default) is the entry
25
- * list; "canvas" renders the document's page as a page miniature and the
26
- * root-level surfaces' elements on one canvas (see CanvasView). The
27
- * `formatPalette` prop overrides the floating format toolbar's color
28
- * palette.
29
- */
30
- declare function Editor({ view, formatPalette }: EditorProps): import("react").JSX.Element;
31
- //#endregion
32
- export { EditorView as n, Editor as t };
@@ -1,13 +0,0 @@
1
- import { c as cn } from "./constants-D4FTL0ph.mjs";
2
- import "react";
3
- import { jsx } from "react/jsx-runtime";
4
- //#region src/shared/ui/Skeleton.tsx
5
- function Skeleton({ className, ...props }) {
6
- return /* @__PURE__ */ jsx("div", {
7
- "data-slot": "skeleton",
8
- className: cn("animate-pulse rounded-md bg-gray-300 dark:bg-gray-700", className),
9
- ...props
10
- });
11
- }
12
- //#endregion
13
- export { Skeleton as t };
@@ -1,8 +0,0 @@
1
- import { n as EditorView } from "../Editor-DT7RkRXf.mjs";
2
- //#region src/motion/MotionEditor.d.ts
3
- declare function MotionEditor({ view, formatPalette }: {
4
- view?: EditorView;
5
- formatPalette?: readonly string[];
6
- }): import("react").JSX.Element;
7
- //#endregion
8
- export { MotionEditor };