@quillmark/svelte 0.5.1 → 0.7.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.
Files changed (66) hide show
  1. package/README.md +6 -0
  2. package/THEMING.md +13 -17
  3. package/dist/core/address.d.ts +17 -3
  4. package/dist/core/address.js +20 -3
  5. package/dist/core/codec/blocks.d.ts +37 -0
  6. package/dist/core/codec/blocks.js +163 -0
  7. package/dist/core/codec/field.js +5 -6
  8. package/dist/core/codec/index.d.ts +1 -1
  9. package/dist/core/codec/index.js +3 -2
  10. package/dist/core/codec/inputrules.js +24 -144
  11. package/dist/core/codec/prose.css +14 -25
  12. package/dist/core/codec/schema.d.ts +8 -0
  13. package/dist/core/codec/schema.js +33 -1
  14. package/dist/core/codec/slash.d.ts +18 -16
  15. package/dist/core/codec/slash.js +0 -0
  16. package/dist/core/codec/table-view.d.ts +4 -0
  17. package/dist/core/codec/table-view.js +137 -158
  18. package/dist/core/codec/table.d.ts +0 -10
  19. package/dist/core/codec/table.js +0 -15
  20. package/dist/core/theme.css +357 -346
  21. package/dist/preset/recipes.css +25 -21
  22. package/dist/preview/Preview.svelte +4 -2
  23. package/dist/preview/bridge.d.ts +23 -0
  24. package/dist/preview/bridge.js +92 -35
  25. package/dist/preview/controller.d.ts +6 -5
  26. package/dist/preview/controller.js +13 -7
  27. package/dist/preview/geometry.d.ts +10 -9
  28. package/dist/preview/geometry.js +11 -13
  29. package/dist/preview/index.js +3 -2
  30. package/dist/preview/paint.js +9 -1
  31. package/dist/visual/ArrayField.svelte +246 -63
  32. package/dist/visual/ArrayField.svelte.d.ts +5 -1
  33. package/dist/visual/Card.svelte +84 -50
  34. package/dist/visual/EnumField.svelte +37 -3
  35. package/dist/visual/Field.svelte +28 -4
  36. package/dist/visual/FieldLabel.svelte +2 -2
  37. package/dist/visual/FormatPopover.svelte +13 -1
  38. package/dist/visual/ObjectField.svelte +128 -35
  39. package/dist/visual/ObjectField.svelte.d.ts +11 -4
  40. package/dist/visual/ProseArrayElement.svelte +22 -2
  41. package/dist/visual/ProseArrayElement.svelte.d.ts +1 -0
  42. package/dist/visual/SlashMenu.svelte +7 -0
  43. package/dist/visual/TipsCard.svelte +33 -13
  44. package/dist/visual/VariantField.svelte +95 -0
  45. package/dist/visual/VariantField.svelte.d.ts +21 -0
  46. package/dist/visual/VisualEditorInner.svelte +44 -21
  47. package/dist/visual/controls.css +282 -283
  48. package/dist/visual/diagnostics.d.ts +13 -11
  49. package/dist/visual/diagnostics.js +11 -9
  50. package/dist/visual/domid.d.ts +13 -0
  51. package/dist/visual/domid.js +16 -0
  52. package/dist/visual/hold.d.ts +17 -0
  53. package/dist/visual/hold.js +39 -0
  54. package/dist/visual/index.js +1 -1
  55. package/dist/visual/leaves.d.ts +9 -7
  56. package/dist/visual/links.d.ts +5 -2
  57. package/dist/visual/links.js +9 -3
  58. package/dist/visual/motion.d.ts +9 -0
  59. package/dist/visual/motion.js +10 -2
  60. package/dist/visual/strings.d.ts +15 -0
  61. package/dist/visual/strings.js +3 -0
  62. package/dist/visual/structure.d.ts +32 -6
  63. package/dist/visual/structure.js +49 -3
  64. package/package.json +2 -2
  65. package/dist/core/codec/clipboard.d.ts +0 -59
  66. package/dist/core/codec/clipboard.js +0 -202
@@ -66,7 +66,7 @@
66
66
  } from './diagnostics.js';
67
67
  import { fieldDomIds, groupPanelId } from './domid.js';
68
68
  import { createLeafRegistry, type FieldControl } from './leaves.js';
69
- import { reorder } from './motion.js';
69
+ import { reorder, reorderTrips } from './motion.js';
70
70
  import { tipsChannel } from './tips.js';
71
71
  import { patchEditorExt } from './ext.js';
72
72
  import Card from './Card.svelte';
@@ -185,6 +185,9 @@
185
185
  };
186
186
  let mainCard = $state<CardHandle | undefined>(undefined);
187
187
  let cardRefs = $state<(CardHandle | undefined)[]>([]);
188
+ /** The slot each card sits in: what a reorder animates, and so what the post-mutation
189
+ * scroll waits on before it measures anything. */
190
+ let slotEls = $state<(HTMLElement | undefined)[]>([]);
188
191
  /** The stack's own element: it carries `data-qm-root`, so it is what the kind
189
192
  * menu portals into, the way each leaf's surface resolves its nearest root. */
190
193
  let rootEl = $state<HTMLElement | undefined>(undefined);
@@ -327,16 +330,29 @@
327
330
  * on a document of any length an insert lands off-screen, and a
328
331
  * viewport that does not follow reads as nothing happening.
329
332
  *
330
- * Coalesced on a single pending id: two quick adds resolve their `tick()` in
331
- * order, the earlier one sees a newer pending id and drops out, so one smooth
332
- * scroll runs to the last card rather than two fighting over the same scroller.
333
+ * Coalesced on the last call: each takes a ticket and a continuation holding a stale
334
+ * one drops out, so two mutations inside a tick run one smooth scroll to the last of
335
+ * them rather than two fighting over the same scroller. A ticket rather than the id
336
+ * being scrolled to, because an insert and a move of the *same* card are two calls
337
+ * naming one id, on different terms — `center` against `nearest`.
333
338
  */
334
- let pendingScrollId: string | null = null;
339
+ let scrollTicket = 0;
335
340
  async function scrollCardIntoView(id: string, block: ScrollLogicalPosition): Promise<void> {
336
- pendingScrollId = id;
341
+ const ticket = ++scrollTicket;
337
342
  if (!(await span.resumes(tick()))) return;
338
- if (pendingScrollId !== id) return;
339
- pendingScrollId = null;
343
+ if (ticket !== scrollTicket) return;
344
+ // A reorder is running by this flush and holds the slot at its pre-move position
345
+ // for the length of the trip (`motion.ts`), so asking now measures the box the
346
+ // card is leaving — where a `nearest` would take the stack back to for the card
347
+ // that moved in from off screen. The trip says the card moved; the scroll follows
348
+ // it to where it landed. `allSettled`, because a second reorder cancels the first
349
+ // and a cancelled run rejects.
350
+ const slot = slotEls[cardIndexOf(id)];
351
+ const trips = slot ? reorderTrips(slot) : [];
352
+ if (trips.length) {
353
+ if (!(await span.resumes(Promise.allSettled(trips.map((trip) => trip.finished))))) return;
354
+ if (ticket !== scrollTicket) return;
355
+ }
340
356
  const i = cardIndexOf(id);
341
357
  if (i >= 0) cardRefs[i]?.scrollIntoViewCard(block);
342
358
  }
@@ -668,14 +684,15 @@
668
684
 
669
685
  /**
670
686
  * Put the caret in a revealed target, at the finest grain it can take: a USV offset
671
- * in a prose leaf, a bare focus everywhere else. An array element is no
672
- * `createField` leaf, and a form control has no coordinate to spend an offset in (an
673
- * `<input type="number">` refuses a selection outright), which is also the whole of
674
- * what a click on plate-placed ink can mean.
687
+ * in a prose leaf or an array element, a bare focus everywhere else. A form control
688
+ * has no coordinate to spend an offset in (an `<input type="number">` refuses a
689
+ * selection outright), which is also the whole of what a click on plate-placed ink
690
+ * can mean. An element is no `createField` leaf, so the offset goes down the element
691
+ * lane instead, where what it means is the row control's (`leaves.ts`).
675
692
  */
676
693
  function land(found: Landed, pos: number | undefined): void {
677
694
  if (found.element != null && found.control.focusElement) {
678
- return found.control.focusElement(found.element);
695
+ return found.control.focusElement(found.element, pos);
679
696
  }
680
697
  if (pos != null) {
681
698
  const prose = leaves.prose(found.key);
@@ -812,7 +829,7 @@
812
829
  rather than being slid across. It is also the shape `animate:` asks for, being the
813
830
  keyed block's only child. -->
814
831
  {#each model.cards as c, i (c.id)}
815
- <div class="qm-card-slot" animate:reorder={isReordering}>
832
+ <div class="qm-card-slot" bind:this={slotEls[i]} animate:reorder={isReordering}>
816
833
  <Card
817
834
  bind:this={cardRefs[i]}
818
835
  card={c}
@@ -873,10 +890,12 @@
873
890
  >{marked ? merged.addCard : ''}</DropdownMenu.Trigger
874
891
  >
875
892
  <DropdownMenu.Portal to={rootEl}>
876
- <DropdownMenu.Content sideOffset={4}>
893
+ <DropdownMenu.Content collisionBoundary={rootEl ?? []} sideOffset={4}>
877
894
  <!-- Portalled out of the row but into the stack's root, and carrying the
878
895
  marker itself: floating is still a detached subtree to the
879
- derivation, like FormatPopover and the enum listbox. -->
896
+ derivation, like FormatPopover and the enum listbox. The root is the
897
+ flip's boundary for the reason it is theirs: it is the box that clips
898
+ the surface where the consumer scrolls one. -->
880
899
  <div class="qm-menu-surface" data-qm-root>
881
900
  {#each kinds as k (k)}
882
901
  <DropdownMenu.Item class="qm-menu-item" onSelect={() => addCard(atIndex, k)}
@@ -898,9 +917,13 @@
898
917
 
899
918
  The column, not only the cards in it: the gutter the stack sits in and the tone
900
919
  behind it are the surface's own, so a bare `<div>` is a mounting site and nothing
901
- is owed before the editor looks right. Consumer CSS is unlayered and beats all of
902
- it, which is how a host that wants the column back takes it. `border-box`, so a
903
- height from the caller is the height this draws.
920
+ is owed before the editor looks right. `border-box`, so a height from the caller is
921
+ the height this draws.
922
+
923
+ `:global(:where(…))` puts a promised class at zero rank, and both halves are
924
+ load-bearing: `:global` drops the scoping class, `:where` drops the rest
925
+ (ARCHITECTURE §Styling). The class is the surface's root wherever it mounts, so
926
+ leaving the component's scope costs nothing.
904
927
 
905
928
  The sunken rung, which is what makes a card an island: the cards are the base
906
929
  plane and this is the one they float on, so the gutter reads as ground rather
@@ -908,7 +931,7 @@
908
931
  ramp, which is what gives the ground enough of itself to read as ground: at a
909
932
  narrower one the stack meets whatever frames the surface and the islands are
910
933
  back to being one block clipped at its edges. */
911
- .qm-editor {
934
+ :global(:where(.qm-editor)) {
912
935
  box-sizing: border-box;
913
936
  display: flex;
914
937
  flex-direction: column;
@@ -933,7 +956,7 @@
933
956
  site with no height of its own, which is the page form kept. The cards do not
934
957
  shrink to fit: a flex item's automatic minimum floors each at its own height, so
935
958
  the stack overflows and scrolls rather than squashing. */
936
- .qm-editor.qm-pane {
959
+ :global(:where(.qm-editor.qm-pane)) {
937
960
  height: 100%;
938
961
  overflow: auto;
939
962
  overscroll-behavior: contain;