noteloom 0.2.0 → 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/style.css CHANGED
@@ -116,6 +116,20 @@
116
116
  outline: none;
117
117
  }
118
118
 
119
+ /* A run with marks.commentIds set (see src/comments/commentMarks.js) --
120
+ presence/absence only, no per-comment value to vary the color by.
121
+ cursor: pointer hints that it opens CommentPopover on click. */
122
+ .be-comment-highlight {
123
+ background: rgba(234, 179, 8, 0.2);
124
+ border-bottom: 2px solid rgba(234, 179, 8, 0.6);
125
+ cursor: pointer;
126
+ }
127
+
128
+ /* Echoes a hover from the panel/popover back onto the actual text -- see useHoveredComment. */
129
+ .be-comment-highlight-active {
130
+ background: rgba(234, 179, 8, 0.4);
131
+ }
132
+
119
133
  /* --- basic leaf blocks --- */
120
134
 
121
135
  .be-paragraph {
@@ -1703,6 +1717,67 @@ tr.be-table-row:hover .be-table-delete-row {
1703
1717
  color: var(--noteloom-danger);
1704
1718
  }
1705
1719
 
1720
+ /* --- template picker (see TemplatePicker.jsx) --- */
1721
+
1722
+ .be-template-picker {
1723
+ list-style: none;
1724
+ margin: 0;
1725
+ padding: 0;
1726
+ display: flex;
1727
+ flex-direction: column;
1728
+ gap: 6px;
1729
+ }
1730
+
1731
+ .be-template-picker-empty {
1732
+ color: var(--noteloom-text-faint);
1733
+ font-size: 0.88rem;
1734
+ }
1735
+
1736
+ .be-template-card {
1737
+ display: flex;
1738
+ align-items: center;
1739
+ justify-content: space-between;
1740
+ gap: 12px;
1741
+ padding: 10px 12px;
1742
+ border: 1px solid var(--noteloom-border);
1743
+ border-radius: var(--noteloom-radius-md);
1744
+ background: var(--noteloom-bg);
1745
+ }
1746
+
1747
+ .be-template-card-body {
1748
+ display: flex;
1749
+ flex-direction: column;
1750
+ gap: 2px;
1751
+ min-width: 0;
1752
+ }
1753
+
1754
+ .be-template-card-name {
1755
+ font-weight: 600;
1756
+ font-size: 0.92rem;
1757
+ color: var(--noteloom-text);
1758
+ }
1759
+
1760
+ .be-template-card-description {
1761
+ font-size: 0.82rem;
1762
+ color: var(--noteloom-text-muted);
1763
+ }
1764
+
1765
+ .be-template-card-select {
1766
+ flex: none;
1767
+ border: 1px solid var(--noteloom-border);
1768
+ background: var(--noteloom-bg-subtle);
1769
+ color: var(--noteloom-text);
1770
+ border-radius: var(--noteloom-radius-sm);
1771
+ padding: 5px 12px;
1772
+ font-size: 0.85rem;
1773
+ font-weight: 500;
1774
+ cursor: pointer;
1775
+ }
1776
+
1777
+ .be-template-card-select:hover {
1778
+ background: var(--noteloom-bg-hover);
1779
+ }
1780
+
1706
1781
  /* --- mobile action bar (pinned above the on-screen keyboard) --- */
1707
1782
 
1708
1783
  .be-mobile-action-bar {
@@ -2375,6 +2450,323 @@ tr.be-table-row:hover .be-table-delete-row {
2375
2450
  color: var(--noteloom-text);
2376
2451
  }
2377
2452
 
2453
+ /* --- comments: avatar, header, composer, thread card, click/hover popover, right-side panel --- */
2454
+
2455
+ .be-comment-avatar {
2456
+ flex: none;
2457
+ display: flex;
2458
+ align-items: center;
2459
+ justify-content: center;
2460
+ border-radius: 50%;
2461
+ color: #fff;
2462
+ font-weight: 700;
2463
+ line-height: 1;
2464
+ }
2465
+
2466
+ /* Shared by CommentPopover and FloatingToolbar's standalone composer (see
2467
+ CommentPopoverHeader.jsx) -- title on the left, an explicit close button
2468
+ on the right so dismissing doesn't rely solely on Escape/outside-click. */
2469
+ .be-comment-popover-header {
2470
+ display: flex;
2471
+ align-items: center;
2472
+ justify-content: space-between;
2473
+ gap: 8px;
2474
+ margin-bottom: 10px;
2475
+ padding-bottom: 10px;
2476
+ border-bottom: 1px solid var(--noteloom-border);
2477
+ }
2478
+
2479
+ .be-comment-popover-title {
2480
+ font-weight: 700;
2481
+ font-size: 0.9rem;
2482
+ }
2483
+
2484
+ .be-comment-popover-close {
2485
+ flex: none;
2486
+ border: none;
2487
+ background: transparent;
2488
+ color: var(--noteloom-text-muted);
2489
+ width: 22px;
2490
+ height: 22px;
2491
+ display: flex;
2492
+ align-items: center;
2493
+ justify-content: center;
2494
+ border-radius: var(--noteloom-radius-sm);
2495
+ cursor: pointer;
2496
+ }
2497
+
2498
+ .be-comment-popover-close:hover {
2499
+ background: var(--noteloom-bg-hover);
2500
+ color: var(--noteloom-text);
2501
+ }
2502
+
2503
+ /* Overrides the dark `.be-floating-toolbar` chrome it also carries (see
2504
+ FloatingToolbar.jsx's own comment on why that base class stays) -- a
2505
+ comment composer reads better as a light card than white text on the
2506
+ toolbar's own near-black background. */
2507
+ .be-floating-toolbar.be-floating-toolbar-comment-standalone {
2508
+ display: block;
2509
+ background: var(--noteloom-bg);
2510
+ border: 1px solid var(--noteloom-border);
2511
+ padding: 10px 12px 12px;
2512
+ width: 300px;
2513
+ }
2514
+
2515
+ .be-comment-composer {
2516
+ display: flex;
2517
+ flex-direction: column;
2518
+ gap: 10px;
2519
+ margin-top: 10px;
2520
+ }
2521
+
2522
+ .be-comment-composer-input-row {
2523
+ display: flex;
2524
+ align-items: flex-start;
2525
+ gap: 8px;
2526
+ }
2527
+
2528
+ .be-comment-composer-textarea {
2529
+ flex: 1;
2530
+ min-width: 0;
2531
+ box-sizing: border-box;
2532
+ resize: none;
2533
+ /* ~2 lines to start, grows with content (see CommentComposer's own
2534
+ resizeToContent) up to ~5 lines, then scrolls. */
2535
+ min-height: 2.8em;
2536
+ max-height: 7.2em;
2537
+ overflow-y: auto;
2538
+ padding: 8px 10px;
2539
+ font: inherit;
2540
+ font-size: 0.85rem;
2541
+ line-height: 1.4;
2542
+ color: var(--noteloom-text);
2543
+ background: var(--noteloom-bg-subtle);
2544
+ border: 1px solid var(--noteloom-border);
2545
+ border-radius: var(--noteloom-radius-md);
2546
+ }
2547
+
2548
+ .be-comment-composer-textarea:focus {
2549
+ outline: none;
2550
+ border-color: var(--noteloom-accent);
2551
+ }
2552
+
2553
+ .be-comment-composer-actions {
2554
+ display: flex;
2555
+ justify-content: flex-end;
2556
+ gap: 8px;
2557
+ }
2558
+
2559
+ .be-comment-composer-cancel,
2560
+ .be-comment-composer-submit {
2561
+ display: flex;
2562
+ align-items: center;
2563
+ gap: 6px;
2564
+ border: none;
2565
+ border-radius: var(--noteloom-radius-md);
2566
+ padding: 6px 12px;
2567
+ font-size: 0.8rem;
2568
+ font-weight: 600;
2569
+ cursor: pointer;
2570
+ }
2571
+
2572
+ .be-comment-composer-cancel {
2573
+ background: var(--noteloom-bg-hover);
2574
+ color: var(--noteloom-text-muted);
2575
+ }
2576
+
2577
+ .be-comment-composer-submit {
2578
+ background: var(--noteloom-accent);
2579
+ color: #fff;
2580
+ }
2581
+
2582
+ .be-comment-composer-submit:disabled {
2583
+ opacity: 0.4;
2584
+ cursor: not-allowed;
2585
+ }
2586
+
2587
+ .be-comment-thread {
2588
+ font-size: 0.85rem;
2589
+ }
2590
+
2591
+ .be-comment-thread + .be-comment-thread {
2592
+ margin-top: 16px;
2593
+ padding-top: 16px;
2594
+ border-top: 1px solid var(--noteloom-border);
2595
+ }
2596
+
2597
+ .be-comment-thread-resolved {
2598
+ opacity: 0.6;
2599
+ }
2600
+
2601
+ /* Echoes a hover from the highlighted text back onto this card -- see useHoveredComment. */
2602
+ .be-comment-thread-hovered {
2603
+ background: var(--noteloom-bg-hover);
2604
+ border-radius: var(--noteloom-radius-md);
2605
+ margin: -6px;
2606
+ padding: 6px;
2607
+ }
2608
+
2609
+ .be-comment-message {
2610
+ display: flex;
2611
+ align-items: flex-start;
2612
+ gap: 10px;
2613
+ }
2614
+
2615
+ .be-comment-message + .be-comment-message {
2616
+ margin-top: 10px;
2617
+ }
2618
+
2619
+ .be-comment-message-body {
2620
+ flex: 1;
2621
+ min-width: 0;
2622
+ }
2623
+
2624
+ .be-comment-message-header {
2625
+ display: flex;
2626
+ align-items: baseline;
2627
+ gap: 6px;
2628
+ }
2629
+
2630
+ .be-comment-message-author {
2631
+ font-weight: 600;
2632
+ font-size: 0.78rem;
2633
+ }
2634
+
2635
+ .be-comment-message-time {
2636
+ font-size: 0.72rem;
2637
+ color: var(--noteloom-text-muted);
2638
+ }
2639
+
2640
+ .be-comment-message-text {
2641
+ margin: 3px 0 0;
2642
+ line-height: 1.45;
2643
+ white-space: pre-wrap;
2644
+ word-break: break-word;
2645
+ }
2646
+
2647
+ /* Replies (every message after the thread's first) get a connecting
2648
+ vertical line + indent, chat-thread style -- our data model has no
2649
+ deeper nesting than "root message + flat replies", so one indent level
2650
+ is all this needs. */
2651
+ .be-comment-thread-replies {
2652
+ margin: 10px 0 0 13px;
2653
+ padding-left: 14px;
2654
+ border-left: 2px solid var(--noteloom-border);
2655
+ }
2656
+
2657
+ .be-comment-thread-actions {
2658
+ display: flex;
2659
+ align-items: center;
2660
+ gap: 4px;
2661
+ margin-top: 10px;
2662
+ opacity: 0;
2663
+ transition: opacity 0.1s ease;
2664
+ }
2665
+
2666
+ .be-comment-thread:hover .be-comment-thread-actions,
2667
+ .be-comment-thread:focus-within .be-comment-thread-actions {
2668
+ opacity: 1;
2669
+ }
2670
+
2671
+ .be-comment-thread-actions button {
2672
+ display: flex;
2673
+ align-items: center;
2674
+ gap: 4px;
2675
+ border: none;
2676
+ background: transparent;
2677
+ color: var(--noteloom-text-muted);
2678
+ font-size: 0.78rem;
2679
+ padding: 4px 8px;
2680
+ border-radius: var(--noteloom-radius-sm);
2681
+ cursor: pointer;
2682
+ }
2683
+
2684
+ .be-comment-thread-actions button:hover {
2685
+ background: var(--noteloom-bg-hover);
2686
+ color: var(--noteloom-text);
2687
+ }
2688
+
2689
+ .be-comment-thread-delete {
2690
+ margin-left: auto;
2691
+ }
2692
+
2693
+ /* --- comments: click/hover popover over existing highlighted text --- */
2694
+
2695
+ .be-comment-popover {
2696
+ z-index: 1000;
2697
+ width: 300px;
2698
+ max-width: calc(100vw - 24px);
2699
+ background: var(--noteloom-bg);
2700
+ border: 1px solid var(--noteloom-border);
2701
+ border-radius: var(--noteloom-radius-lg);
2702
+ padding: 12px 14px 14px;
2703
+ box-shadow: var(--noteloom-shadow);
2704
+ }
2705
+
2706
+ /* --- comments: opt-in right-side panel (NoteloomEditor showCommentsPanel) --- */
2707
+
2708
+ /* Deliberately no border/shadow/box background here, or on
2709
+ .be-comments-panel-item below -- comments float directly on the page
2710
+ like margin notes, not a boxed widget, matching how most other editors'
2711
+ own comment sidebars read. */
2712
+ /* No overflow/scrolling of its own on purpose -- each card's position
2713
+ already tracks the PAGE's scroll (see CommentsPanel's recompute()), so
2714
+ the panel scrolling independently would fight that: a wheel gesture over
2715
+ it needs to fall through and scroll the page, not the panel's own box,
2716
+ or cards visually detach from the text they're anchored to. Cards whose
2717
+ anchor has scrolled off-screen just go negative/beyond the viewport and
2718
+ aren't painted -- no clipping box needed for that. */
2719
+ .be-comments-panel {
2720
+ position: fixed;
2721
+ top: 80px;
2722
+ right: 24px;
2723
+ width: 320px;
2724
+ overflow: visible;
2725
+ background: transparent;
2726
+ padding: 0 12px;
2727
+ font-size: 0.85rem;
2728
+ z-index: 500;
2729
+ pointer-events: none;
2730
+ }
2731
+
2732
+ .be-comments-panel-item,
2733
+ .be-comments-panel-empty {
2734
+ pointer-events: auto;
2735
+ }
2736
+
2737
+ .be-comments-panel-empty {
2738
+ color: var(--noteloom-text-muted);
2739
+ font-size: 0.82rem;
2740
+ margin: 0;
2741
+ }
2742
+
2743
+ /* Each .be-comments-panel-item is absolutely positioned (top set inline by
2744
+ CommentsPanel, aligned with its thread's own anchored text, margin-comment
2745
+ style) inside this relatively-positioned container -- height is also set
2746
+ inline, sized to fit the lowest card. */
2747
+ .be-comments-panel-list {
2748
+ position: relative;
2749
+ }
2750
+
2751
+ .be-comments-panel-item {
2752
+ position: absolute;
2753
+ left: 0;
2754
+ right: 0;
2755
+ padding: 8px 12px;
2756
+ border-radius: var(--noteloom-radius-md);
2757
+ transition: top 0.15s ease, background-color 0.1s ease;
2758
+ }
2759
+
2760
+ .be-comments-panel-item:hover {
2761
+ background: var(--noteloom-bg-hover);
2762
+ }
2763
+
2764
+ @media (max-width: 900px) {
2765
+ .be-comments-panel {
2766
+ display: none;
2767
+ }
2768
+ }
2769
+
2378
2770
  /* --- voice typing: caret-anchored listening/processing indicator --- */
2379
2771
 
2380
2772
  .be-voice-indicator {
@@ -2458,6 +2850,8 @@ tr.be-table-row:hover .be-table-delete-row {
2458
2850
  #be-at-menu,
2459
2851
  .be-floating-toolbar,
2460
2852
  .be-link-hover-card,
2853
+ .be-comment-popover,
2854
+ .be-comments-panel,
2461
2855
  .be-voice-indicator,
2462
2856
  .be-table-header-menu-trigger,
2463
2857
  .be-table-header-menu,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "noteloom",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Zero-runtime-dependency, React-first block/rich-text editor — nestable content blocks, inline widgets, slash commands, undo/redo, clipboard, real-time collaborative editing (a custom CRDT over WebRTC), offline-first persistence (IndexedDB + PWA-ready), and live presence, with an optional default theme (noteloom/style.css).",
5
5
  "keywords": [
6
6
  "react",
@@ -57,11 +57,15 @@
57
57
  "dev:custom-block": "vite --config examples/02-custom-block/vite.config.js",
58
58
  "dev:custom-field-type": "vite --config examples/03-custom-field-type/vite.config.js",
59
59
  "dev:styling": "vite --config examples/04-styling/vite.config.js",
60
+ "dev:templates": "vite --config examples/05-templates/vite.config.js",
61
+ "dev:comments": "vite --config examples/06-comments/vite.config.js",
62
+ "dev:version-history": "vite --config examples/07-version-history/vite.config.js",
60
63
  "dev:collab": "vite --config examples/collab/vite.config.js",
61
64
  "dev:lan-collab": "vite --config examples/lan-collab/vite.config.js",
62
65
  "dev:offline-persist": "vite --config examples/offline-persist/vite.config.js",
63
66
  "build": "vite build && node -e \"require('fs').copyFileSync('src/style.css','dist/style.css');require('fs').copyFileSync('src/index.d.ts','dist/index.d.ts')\"",
64
67
  "test": "vitest run",
68
+ "test:e2e": "playwright test",
65
69
  "typecheck": "tsc",
66
70
  "prepublishOnly": "npm test && npm run typecheck && npm run build"
67
71
  },
@@ -70,6 +74,7 @@
70
74
  "react-dom": "^18.2.0 || ^19.0.0"
71
75
  },
72
76
  "devDependencies": {
77
+ "@playwright/test": "^1.62.0",
73
78
  "@testing-library/jest-dom": "^6.4.0",
74
79
  "@testing-library/react": "^16.0.0",
75
80
  "@types/react": "^18.3.0",