@particle-academy/react-fancy 5.69.0 → 5.70.1

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 (132) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/dist/autocomplete.cjs +3 -2
  3. package/dist/autocomplete.js +2 -1
  4. package/dist/chunk-2C64OVOZ.cjs +18 -0
  5. package/dist/chunk-2C64OVOZ.cjs.map +1 -0
  6. package/dist/{chunk-BX7EDTL4.js → chunk-37D5PYEF.js} +4 -3
  7. package/dist/chunk-37D5PYEF.js.map +1 -0
  8. package/dist/{chunk-UJRMY54A.cjs → chunk-3QCAOD2W.cjs} +4 -2
  9. package/dist/chunk-3QCAOD2W.cjs.map +1 -0
  10. package/dist/{chunk-KSU6RYWU.cjs → chunk-3T3LBIQA.cjs} +4 -2
  11. package/dist/chunk-3T3LBIQA.cjs.map +1 -0
  12. package/dist/{chunk-O4KZYGGC.cjs → chunk-5YRSYS2F.cjs} +10 -10
  13. package/dist/{chunk-O4KZYGGC.cjs.map → chunk-5YRSYS2F.cjs.map} +1 -1
  14. package/dist/{chunk-2PSHIUM7.cjs → chunk-6EA3DSPT.cjs} +14 -13
  15. package/dist/chunk-6EA3DSPT.cjs.map +1 -0
  16. package/dist/{chunk-4WIPWJYD.js → chunk-6PRXG7L6.js} +4 -3
  17. package/dist/chunk-6PRXG7L6.js.map +1 -0
  18. package/dist/{chunk-WKPBCB67.cjs → chunk-6QAF35AJ.cjs} +4 -2
  19. package/dist/chunk-6QAF35AJ.cjs.map +1 -0
  20. package/dist/chunk-6V44RRSB.cjs +11 -0
  21. package/dist/chunk-6V44RRSB.cjs.map +1 -0
  22. package/dist/{chunk-G35XN5WV.js → chunk-CDW7MFPG.js} +4 -2
  23. package/dist/chunk-CDW7MFPG.js.map +1 -0
  24. package/dist/{chunk-U4PWNLOH.js → chunk-EZL5DILH.js} +7 -6
  25. package/dist/chunk-EZL5DILH.js.map +1 -0
  26. package/dist/{chunk-ARO2DNGS.js → chunk-EZZKHMR4.js} +4 -2
  27. package/dist/chunk-EZZKHMR4.js.map +1 -0
  28. package/dist/{chunk-LLVYCACC.js → chunk-F4GMOMUT.js} +3 -3
  29. package/dist/{chunk-LLVYCACC.js.map → chunk-F4GMOMUT.js.map} +1 -1
  30. package/dist/{chunk-R6URPHEP.cjs → chunk-FHRVSYJU.cjs} +4 -3
  31. package/dist/chunk-FHRVSYJU.cjs.map +1 -0
  32. package/dist/{chunk-HRZDEZSE.js → chunk-FYUEDPST.js} +95 -23
  33. package/dist/chunk-FYUEDPST.js.map +1 -0
  34. package/dist/{chunk-4UEIMGHZ.js → chunk-GDH43QH6.js} +59 -11
  35. package/dist/chunk-GDH43QH6.js.map +1 -0
  36. package/dist/{chunk-J5TFVYYM.cjs → chunk-HNJXBMHI.cjs} +6 -6
  37. package/dist/{chunk-J5TFVYYM.cjs.map → chunk-HNJXBMHI.cjs.map} +1 -1
  38. package/dist/chunk-I3LAFKJU.js +16 -0
  39. package/dist/chunk-I3LAFKJU.js.map +1 -0
  40. package/dist/chunk-J6IQHJET.js +76 -0
  41. package/dist/chunk-J6IQHJET.js.map +1 -0
  42. package/dist/chunk-JKD6CFIP.cjs +78 -0
  43. package/dist/chunk-JKD6CFIP.cjs.map +1 -0
  44. package/dist/{chunk-YJETQ76J.cjs → chunk-KKYILQTG.cjs} +4 -3
  45. package/dist/chunk-KKYILQTG.cjs.map +1 -0
  46. package/dist/{chunk-FVI4JDLA.js → chunk-M6UAVA2I.js} +4 -2
  47. package/dist/chunk-M6UAVA2I.js.map +1 -0
  48. package/dist/{chunk-Z6RA37IC.js → chunk-NAYXNVNU.js} +3 -15
  49. package/dist/chunk-NAYXNVNU.js.map +1 -0
  50. package/dist/{chunk-FPFQBYKJ.cjs → chunk-NPSKZ7ZB.cjs} +65 -17
  51. package/dist/chunk-NPSKZ7ZB.cjs.map +1 -0
  52. package/dist/{chunk-G5DMYAWL.cjs → chunk-O5ORO2RX.cjs} +5 -2
  53. package/dist/chunk-O5ORO2RX.cjs.map +1 -0
  54. package/dist/{chunk-YEGFOMJB.js → chunk-PJNUGSKI.js} +3 -3
  55. package/dist/{chunk-YEGFOMJB.js.map → chunk-PJNUGSKI.js.map} +1 -1
  56. package/dist/{chunk-ISNS4GAW.cjs → chunk-PS7C6GKI.cjs} +100 -28
  57. package/dist/chunk-PS7C6GKI.cjs.map +1 -0
  58. package/dist/{chunk-KGJ2ORY6.cjs → chunk-R3EJNGJV.cjs} +4 -16
  59. package/dist/chunk-R3EJNGJV.cjs.map +1 -0
  60. package/dist/chunk-S42OGG43.js +9 -0
  61. package/dist/chunk-S42OGG43.js.map +1 -0
  62. package/dist/{chunk-VZNBTCGA.js → chunk-TCMOD3WW.js} +4 -3
  63. package/dist/chunk-TCMOD3WW.js.map +1 -0
  64. package/dist/{chunk-6MXFZ3B5.cjs → chunk-UK6BGM74.cjs} +4 -3
  65. package/dist/chunk-UK6BGM74.cjs.map +1 -0
  66. package/dist/{chunk-XS3EIQFP.js → chunk-WZAKEJDL.js} +5 -2
  67. package/dist/chunk-WZAKEJDL.js.map +1 -0
  68. package/dist/command.cjs +4 -3
  69. package/dist/command.js +2 -1
  70. package/dist/composer.cjs +7 -4
  71. package/dist/composer.d.cts +45 -2
  72. package/dist/composer.d.ts +45 -2
  73. package/dist/composer.js +5 -2
  74. package/dist/content-renderer.cjs +5 -4
  75. package/dist/content-renderer.js +2 -1
  76. package/dist/editor.cjs +5 -4
  77. package/dist/editor.js +3 -2
  78. package/dist/file-browser.cjs +6 -5
  79. package/dist/file-browser.js +2 -1
  80. package/dist/{index-BQi_n6eS.d.ts → index-B8OkuYSt.d.ts} +49 -2
  81. package/dist/{index-n_4_OZK_.d.cts → index-BMVQnKTH.d.cts} +49 -2
  82. package/dist/index.cjs +61 -58
  83. package/dist/index.cjs.map +1 -1
  84. package/dist/index.d.cts +2 -1
  85. package/dist/index.d.ts +2 -1
  86. package/dist/index.js +16 -13
  87. package/dist/index.js.map +1 -1
  88. package/dist/input-tag.cjs +7 -6
  89. package/dist/input-tag.js +2 -1
  90. package/dist/input.cjs +4 -3
  91. package/dist/input.js +3 -2
  92. package/dist/inputs.cjs +6 -5
  93. package/dist/inputs.js +4 -3
  94. package/dist/json-editor.cjs +16 -15
  95. package/dist/json-editor.js +5 -4
  96. package/dist/paste-pills.cjs +15 -14
  97. package/dist/paste-pills.js +2 -1
  98. package/dist/pillbox.cjs +3 -2
  99. package/dist/pillbox.js +2 -1
  100. package/dist/prompt-input.cjs +8 -5
  101. package/dist/prompt-input.d.cts +2 -1
  102. package/dist/prompt-input.d.ts +2 -1
  103. package/dist/prompt-input.js +5 -2
  104. package/dist/select.cjs +3 -2
  105. package/dist/select.js +2 -1
  106. package/dist/use-acknowledged-submit-7nC0vSCP.d.cts +12 -0
  107. package/dist/use-acknowledged-submit-7nC0vSCP.d.ts +12 -0
  108. package/docs/Composer.md +65 -2
  109. package/docs/PromptInput.md +70 -4
  110. package/package.json +1 -1
  111. package/dist/chunk-2PSHIUM7.cjs.map +0 -1
  112. package/dist/chunk-4UEIMGHZ.js.map +0 -1
  113. package/dist/chunk-4WIPWJYD.js.map +0 -1
  114. package/dist/chunk-6MXFZ3B5.cjs.map +0 -1
  115. package/dist/chunk-ARO2DNGS.js.map +0 -1
  116. package/dist/chunk-BX7EDTL4.js.map +0 -1
  117. package/dist/chunk-FPFQBYKJ.cjs.map +0 -1
  118. package/dist/chunk-FVI4JDLA.js.map +0 -1
  119. package/dist/chunk-G35XN5WV.js.map +0 -1
  120. package/dist/chunk-G5DMYAWL.cjs.map +0 -1
  121. package/dist/chunk-HRZDEZSE.js.map +0 -1
  122. package/dist/chunk-ISNS4GAW.cjs.map +0 -1
  123. package/dist/chunk-KGJ2ORY6.cjs.map +0 -1
  124. package/dist/chunk-KSU6RYWU.cjs.map +0 -1
  125. package/dist/chunk-R6URPHEP.cjs.map +0 -1
  126. package/dist/chunk-U4PWNLOH.js.map +0 -1
  127. package/dist/chunk-UJRMY54A.cjs.map +0 -1
  128. package/dist/chunk-VZNBTCGA.js.map +0 -1
  129. package/dist/chunk-WKPBCB67.cjs.map +0 -1
  130. package/dist/chunk-XS3EIQFP.js.map +0 -1
  131. package/dist/chunk-YJETQ76J.cjs.map +0 -1
  132. package/dist/chunk-Z6RA37IC.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -11,6 +11,79 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
11
11
 
12
12
  ## [Unreleased]
13
13
 
14
+ ## [5.70.1] - 2026-10-27
15
+
16
+ ### Fixed
17
+
18
+ - **An acknowledged send no longer clears a newer draft that happens to read
19
+ the same** (`Composer`, `PromptInput`, from 5.70.0). When an async `onSubmit`
20
+ resolved, the draft was cleared if its text and the ids of its pills and
21
+ attachments still matched what was sent. A newer draft that compared equal was
22
+ therefore thrown away: an edit typed and then deleted during the send, a host
23
+ `setDraft` that restored the same draft, or a pill's text or an attachment
24
+ changed under the same id. The clear is now tied to the draft revision that
25
+ was sent. Anything that changes the draft after the send (the person, the
26
+ host's `setDraft`, a controlled `draft` / `value` / `heldPastes` /
27
+ `heldImages` that now says something different) makes it newer, and a newer
28
+ draft is kept whole. A `ref` arriving from `persistAttachment` mid-send is not
29
+ a change, so it does not block the clear. A controlled host that echoes a
30
+ copy of each draft is still cleared, because an echo that says the same thing
31
+ is not a new revision. Nothing to do on upgrade.
32
+ - **Only the newest send can acknowledge.** Both components refuse a second
33
+ send while one is pending, and nothing turns that off. If two ever overlapped,
34
+ the older one settling would have cleared the draft and ended the newer one's
35
+ `submitting` state. It is now ignored, except that its failure still reaches
36
+ `onSubmitError`.
37
+
38
+ ## [5.70.0] - 2026-10-27
39
+
40
+ ### Added
41
+
42
+ - **Acknowledged send for `Composer` and `PromptInput`.** `onSubmit` may now
43
+ return `Promise<void | { ok: false; error?: string }>` (exported as
44
+ `SubmitResult` / `SubmitRejection`). While the Promise is pending, the text,
45
+ held pastes, pills and attachments all stay, the send button is disabled and
46
+ `aria-busy`, and a second send is refused. The text stays editable. If it
47
+ resolves, the draft clears as before. If the person edited it in flight,
48
+ their newer draft is kept. If it rejects or resolves `{ ok: false }`,
49
+ everything is kept, the new `onSubmitError(error)` is called and a visually
50
+ hidden `role="alert"` announces it. The root carries
51
+ `data-submit-state="submitting" | "error"` while not idle. **A void
52
+ `onSubmit` behaves exactly as before; nothing to do on upgrade.** One
53
+ behaviour does move: an `onSubmit` that ALREADY returned a Promise (an
54
+ `async` handler) used to clear at once. It now clears when the Promise
55
+ resolves and keeps the draft if it rejects. If you relied on the instant
56
+ clear, return nothing (`onSubmit={(t) => { void send(t); }}`).
57
+ - **`sendDisabled`** on both: disables the send while the text stays editable
58
+ (for example, while an agent is still answering).
59
+ - **`PromptInput` `disabled`**, matching `Composer`'s: disables the text, the
60
+ inline editor, attaching, dropping and the send.
61
+ - **`name` and `inputId`** on both, for the text field. `name` sits on the
62
+ textarea, or with inline pills on a hidden input carrying the expanded text.
63
+ `inputId` is the field's `id` in either mode. `PromptInput`'s `id` still
64
+ names the root.
65
+ - **Stable handles**: `data-react-fancy-composer-send`,
66
+ `data-react-fancy-composer-textarea`,
67
+ `data-react-fancy-prompt-input-textarea`, and
68
+ `data-react-fancy-composer-error` / `data-react-fancy-prompt-input-error`.
69
+ `PromptInput`'s default textarea markup gains its one new attribute. The
70
+ inline editor keeps `data-react-fancy-composer-input`. It was not reused on
71
+ the textareas, because hosts already test for it to mean "the contenteditable
72
+ is on".
73
+
74
+ ### Fixed
75
+
76
+ - **Confirming an IME composition with Enter no longer sends, adds or picks.**
77
+ A Japanese, Chinese or Korean typist presses Enter to accept a candidate, and
78
+ these fields treated it as their commit key: `Composer` (textarea, and the
79
+ inline editor on Safari), `PromptInput` (⌘/Ctrl+Enter send and the `/` / `@`
80
+ picker), `Pillbox`, `Command`, `Autocomplete`, `Select` (search and
81
+ create), `InputTag`, `FileBrowser`'s new-folder and path inputs, and
82
+ `JsonEditor`'s commit-on-blur value and key fields. They now ignore an Enter
83
+ with `isComposing`, or with `keyCode` 229. Safari sends that confirming
84
+ keydown after `compositionend`, with `isComposing` already false. Nothing
85
+ to do on upgrade.
86
+
14
87
  ## [5.69.0] - 2026-10-27
15
88
 
16
89
  ### Fixed
@@ -1,9 +1,10 @@
1
1
  'use strict';
2
2
 
3
- var chunkR6URPHEP_cjs = require('./chunk-R6URPHEP.cjs');
3
+ var chunkFHRVSYJU_cjs = require('./chunk-FHRVSYJU.cjs');
4
4
  require('./chunk-KJ22KE56.cjs');
5
5
  require('./chunk-L3V3BYVS.cjs');
6
6
  require('./chunk-J2DI6RMR.cjs');
7
+ require('./chunk-6V44RRSB.cjs');
7
8
  require('./chunk-MKHYENKR.cjs');
8
9
  require('./chunk-TI7D4QDM.cjs');
9
10
  require('./chunk-57FQGQJK.cjs');
@@ -15,7 +16,7 @@ require('./chunk-ZU5Q77OT.cjs');
15
16
 
16
17
  Object.defineProperty(exports, "Autocomplete", {
17
18
  enumerable: true,
18
- get: function () { return chunkR6URPHEP_cjs.Autocomplete; }
19
+ get: function () { return chunkFHRVSYJU_cjs.Autocomplete; }
19
20
  });
20
21
  //# sourceMappingURL=autocomplete.cjs.map
21
22
  //# sourceMappingURL=autocomplete.cjs.map
@@ -1,7 +1,8 @@
1
- export { Autocomplete } from './chunk-VZNBTCGA.js';
1
+ export { Autocomplete } from './chunk-TCMOD3WW.js';
2
2
  import './chunk-OL53XYHF.js';
3
3
  import './chunk-NRXK42LO.js';
4
4
  import './chunk-MQ6VGG62.js';
5
+ import './chunk-S42OGG43.js';
5
6
  import './chunk-5VMILVWD.js';
6
7
  import './chunk-RBCMKPBX.js';
7
8
  import './chunk-RGANGU7X.js';
@@ -0,0 +1,18 @@
1
+ 'use strict';
2
+
3
+ // src/utils/visually-hidden.ts
4
+ var visuallyHidden = {
5
+ position: "absolute",
6
+ width: "1px",
7
+ height: "1px",
8
+ padding: 0,
9
+ margin: "-1px",
10
+ overflow: "hidden",
11
+ clip: "rect(0, 0, 0, 0)",
12
+ whiteSpace: "nowrap",
13
+ border: 0
14
+ };
15
+
16
+ exports.visuallyHidden = visuallyHidden;
17
+ //# sourceMappingURL=chunk-2C64OVOZ.cjs.map
18
+ //# sourceMappingURL=chunk-2C64OVOZ.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/visually-hidden.ts"],"names":[],"mappings":";;;AAcO,IAAM,cAAA,GAAgC;AAAA,EAC3C,QAAA,EAAU,UAAA;AAAA,EACV,KAAA,EAAO,KAAA;AAAA,EACP,MAAA,EAAQ,KAAA;AAAA,EACR,OAAA,EAAS,CAAA;AAAA,EACT,MAAA,EAAQ,MAAA;AAAA,EACR,QAAA,EAAU,QAAA;AAAA,EACV,IAAA,EAAM,kBAAA;AAAA,EACN,UAAA,EAAY,QAAA;AAAA,EACZ,MAAA,EAAQ;AACV","file":"chunk-2C64OVOZ.cjs","sourcesContent":["import type { CSSProperties } from \"react\";\n\n/**\n * The standard sr-only clip pattern as an inline style: the same declarations\n * Tailwind's `sr-only` utility emits. Pair it with `className=\"sr-only\"`.\n *\n * Inline because a visually hidden element must not depend on the host's\n * Tailwind build having generated `sr-only` for react-fancy's classes. Without\n * it the element renders as visible, unclipped text (genie#1290).\n *\n * The element is `position: absolute`, so whatever holds it must be positioned\n * too. Otherwise it escapes to the nearest positioned ancestor, which can sit\n * outside an unpositioned scroll container and stretch the document.\n */\nexport const visuallyHidden: CSSProperties = {\n position: \"absolute\",\n width: \"1px\",\n height: \"1px\",\n padding: 0,\n margin: \"-1px\",\n overflow: \"hidden\",\n clip: \"rect(0, 0, 0, 0)\",\n whiteSpace: \"nowrap\",\n border: 0,\n};\n"]}
@@ -1,7 +1,7 @@
1
+ import { isImeComposing } from './chunk-S42OGG43.js';
1
2
  import { useMemo, useState, useRef, useEffect, useLayoutEffect, useCallback } from 'react';
2
3
  import { jsxs, jsx } from 'react/jsx-runtime';
3
4
 
4
- // src/components/InputTag/InputTag.tsx
5
5
  function defaultKeyOf(item) {
6
6
  if (item && typeof item === "object") {
7
7
  const r = item;
@@ -120,6 +120,7 @@ function InputTag({
120
120
  case "Enter":
121
121
  case "Tab": {
122
122
  if (visible.length === 0) return false;
123
+ if (e.key === "Enter" && isImeComposing(e)) return false;
123
124
  const idx = Math.min(cursorRef.current, visible.length - 1);
124
125
  pickItem(visible[idx]);
125
126
  return true;
@@ -419,5 +420,5 @@ function controlledAdapter(opts) {
419
420
  }
420
421
 
421
422
  export { InputTag, contentEditableAdapter, controlledAdapter, inputAdapter, textareaAdapter };
422
- //# sourceMappingURL=chunk-BX7EDTL4.js.map
423
- //# sourceMappingURL=chunk-BX7EDTL4.js.map
423
+ //# sourceMappingURL=chunk-37D5PYEF.js.map
424
+ //# sourceMappingURL=chunk-37D5PYEF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/InputTag/InputTag.tsx","../src/components/InputTag/adapters.ts"],"names":["cfg","el"],"mappings":"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","file":"chunk-37D5PYEF.js","sourcesContent":["import {\n type CSSProperties,\n type ReactNode,\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { isImeComposing } from \"../../utils/ime\";\n\n/**\n * InputTag — attach a `/`-style or `@`-style autocomplete picker to *any*\n * text surface (a `<textarea>`, an `<input>`, a `contenteditable`, a code\n * editor, a sheet cell editor, a whiteboard sticky note…) via an adapter\n * that abstracts the surface's read/write/caret API.\n *\n * The component is \"headless\" in the sense that it has no input of its\n * own — it floats a small picker menu near the surface and writes back\n * through the adapter when the user picks an item.\n *\n * <textarea ref={ref} value={text} onChange={...} />\n * <InputTag\n * adapter={textareaAdapter(ref)}\n * triggers={{\n * \"/\": { items: commands, insert: (c) => `${c.name} ` },\n * \"@\": { items: mentions, insert: (m) => `@${m.name} ` },\n * }}\n * />\n *\n * For non-DOM surfaces, write a small adapter that conforms to\n * {@link InputTagAdapter}. Adapters typically run 20–40 lines.\n */\n\n/** What the surface tells the picker on every text/caret change. */\nexport type InputTagAdapterState = {\n text: string;\n caretIndex: number;\n};\n\n/**\n * The contract every input surface implements. The picker subscribes to\n * state changes, anchors itself using `getAnchorRect`, intercepts\n * navigation keys via `onKey`, and writes the selected item back through\n * `replaceRange`.\n */\nexport type InputTagAdapter = {\n /** Push current state whenever text or caret changes. Returns an unsubscribe. */\n subscribe: (fn: (state: InputTagAdapterState) => void) => () => void;\n /** Replace text in `[start, end)` with `replacement`. The adapter is\n * responsible for moving the caret to the end of the inserted text. */\n replaceRange: (start: number, end: number, replacement: string) => void;\n /** Screen-space rect to anchor the picker against. Usually the surface's\n * bounding rect; for editors that can compute caret-precise coordinates,\n * return a small rect there instead. */\n getAnchorRect: () => DOMRect | null;\n /** Subscribe to keydown events on the surface. The handler may return\n * `true` to consume the event (the adapter then calls\n * `preventDefault` / `stopPropagation`). Returns an unsubscribe. */\n onKey: (handler: (e: KeyboardEvent) => boolean) => () => void;\n};\n\n/**\n * Per-trigger configuration. `T` is the item shape — typically a\n * `{ id, name, ... }` object, but any shape works as long as `keyOf` /\n * `insert` know how to handle it.\n */\nexport type InputTagTrigger<T> = {\n /** The pool the picker filters against. */\n items: T[];\n /** Text inserted in place of `<triggerChar><query>`. */\n insert: (item: T, query: string) => string;\n /** Custom filter. Default: case-insensitive prefix match against\n * `String(keyOf(item))`. Pass `() => true` to disable filtering and\n * rely on `items` being pre-filtered (e.g. from an async source). */\n filter?: (item: T, query: string) => boolean;\n /** How to render each row. Default renders the result of `keyOf(item)`. */\n render?: (item: T, active: boolean) => ReactNode;\n /** How to derive a stable key + default label for each item. Default\n * reads `item.name` then `item.id` then `String(item)`. */\n keyOf?: (item: T) => string;\n /** Optional header label shown above the list. */\n label?: string;\n};\n\nexport type InputTagTriggers = Record<string, InputTagTrigger<any>>;\n\nexport interface InputTagProps {\n adapter: InputTagAdapter;\n triggers: InputTagTriggers;\n /** Max rows shown. Default 8. */\n maxItems?: number;\n /** Where the picker anchors relative to the surface. Default `\"bottom-left\"`. */\n placement?: \"bottom-left\" | \"bottom-right\" | \"top-left\" | \"top-right\";\n /** Custom class for the popover container. */\n className?: string;\n /** Inline style for the popover container. */\n style?: CSSProperties;\n /** Fires whenever an item is picked. */\n onPick?: (info: { triggerChar: string; query: string; item: unknown }) => void;\n};\n\ntype ActiveTrigger = {\n char: string;\n start: number;\n end: number;\n query: string;\n};\n\nfunction defaultKeyOf(item: unknown): string {\n if (item && typeof item === \"object\") {\n const r = item as Record<string, unknown>;\n if (typeof r.name === \"string\") return r.name;\n if (typeof r.id === \"string\") return r.id;\n }\n return String(item);\n}\n\nfunction defaultFilter(item: unknown, query: string): boolean {\n if (!query) return true;\n return defaultKeyOf(item).toLowerCase().includes(query.toLowerCase());\n}\n\n/**\n * Walk back from `caret` to detect an active trigger. A trigger is active\n * when one of the configured characters appears between `caret` and the\n * nearest preceding whitespace (or start-of-text), with no other\n * non-trigger-non-whitespace breaks. The \"query\" is everything after\n * the trigger up to the caret.\n */\nfunction detectTrigger(\n text: string,\n caret: number,\n triggerChars: Set<string>,\n): ActiveTrigger | null {\n for (let i = caret - 1; i >= 0; i--) {\n const ch = text[i];\n if (ch === undefined) break;\n if (triggerChars.has(ch)) {\n // Must be at a word boundary: start of text OR preceded by whitespace.\n if (i === 0 || /\\s/.test(text[i - 1])) {\n return {\n char: ch,\n start: i,\n end: caret,\n query: text.slice(i + 1, caret),\n };\n }\n return null;\n }\n if (/\\s/.test(ch)) return null;\n }\n return null;\n}\n\nexport function InputTag({\n adapter,\n triggers,\n maxItems = 8,\n placement = \"bottom-left\",\n className,\n style,\n onPick,\n}: InputTagProps) {\n const triggerChars = useMemo(() => new Set(Object.keys(triggers)), [triggers]);\n const [active, setActive] = useState<ActiveTrigger | null>(null);\n const [cursor, setCursor] = useState(0);\n const [anchorRect, setAnchorRect] = useState<DOMRect | null>(null);\n\n // Latest state in refs so key handlers see fresh data without re-registering.\n const stateRef = useRef<InputTagAdapterState>({ text: \"\", caretIndex: 0 });\n const activeRef = useRef<ActiveTrigger | null>(null);\n const cursorRef = useRef(0);\n activeRef.current = active;\n cursorRef.current = cursor;\n\n // Filtered items for the active trigger.\n const items: unknown[] = useMemo(() => {\n if (!active) return [];\n const cfg = triggers[active.char];\n if (!cfg) return [];\n const filter = cfg.filter ?? defaultFilter;\n const out: unknown[] = [];\n for (const item of cfg.items) {\n if (filter(item, active.query)) out.push(item);\n if (out.length >= maxItems) break;\n }\n return out;\n }, [active, triggers, maxItems]);\n\n // Subscribe to text/caret changes.\n useEffect(() => {\n return adapter.subscribe((s) => {\n stateRef.current = s;\n const next = detectTrigger(s.text, s.caretIndex, triggerChars);\n setActive((prev) => {\n // Reset cursor when the trigger char or position changes.\n if (!prev || !next || prev.char !== next.char || prev.start !== next.start) {\n setCursor(0);\n }\n return next;\n });\n if (next) setAnchorRect(adapter.getAnchorRect());\n });\n }, [adapter, triggerChars]);\n\n // Refresh anchor rect on scroll/resize while picker is open.\n useLayoutEffect(() => {\n if (!active) return;\n const update = () => setAnchorRect(adapter.getAnchorRect());\n update();\n window.addEventListener(\"scroll\", update, true);\n window.addEventListener(\"resize\", update);\n return () => {\n window.removeEventListener(\"scroll\", update, true);\n window.removeEventListener(\"resize\", update);\n };\n }, [active, adapter]);\n\n // Clamp cursor when the visible items shrink.\n useEffect(() => {\n if (cursor >= items.length) setCursor(Math.max(0, items.length - 1));\n }, [items.length, cursor]);\n\n const pickItem = useCallback(\n (item: unknown) => {\n const cur = activeRef.current;\n if (!cur) return;\n const cfg = triggers[cur.char];\n if (!cfg) return;\n const replacement = cfg.insert(item, cur.query);\n adapter.replaceRange(cur.start, cur.end, replacement);\n onPick?.({ triggerChar: cur.char, query: cur.query, item });\n setActive(null);\n },\n [adapter, triggers, onPick],\n );\n\n // Key handling.\n useEffect(() => {\n return adapter.onKey((e) => {\n const cur = activeRef.current;\n if (!cur) return false;\n const visible = items;\n switch (e.key) {\n case \"ArrowDown\":\n if (visible.length === 0) return false;\n setCursor((c) => (c + 1) % visible.length);\n return true;\n case \"ArrowUp\":\n if (visible.length === 0) return false;\n setCursor((c) => (c - 1 + visible.length) % visible.length);\n return true;\n case \"Enter\":\n case \"Tab\": {\n if (visible.length === 0) return false;\n // Confirming an IME composition is not a pick; let the editor have it.\n if (e.key === \"Enter\" && isImeComposing(e)) return false;\n const idx = Math.min(cursorRef.current, visible.length - 1);\n pickItem(visible[idx]);\n return true;\n }\n case \"Escape\":\n setActive(null);\n return true;\n default:\n return false;\n }\n });\n }, [adapter, items, pickItem]);\n\n if (!active || !anchorRect || items.length === 0) return null;\n\n const cfg = triggers[active.char];\n if (!cfg) return null;\n\n const popStyle = computePopoverStyle(anchorRect, placement);\n\n return (\n <div\n role=\"listbox\"\n aria-label={cfg.label ?? `Pick a ${active.char === \"/\" ? \"command\" : \"mention\"}`}\n className={[\n \"fixed z-50 w-72 overflow-hidden rounded-md border border-[color:var(--fancy-border,var(--color-zinc-200))] bg-[color:var(--fancy-surface,var(--color-white))] shadow-lg dark:border-[color:var(--fancy-border-dark,var(--color-zinc-700))] dark:bg-[color:var(--fancy-surface-dark,var(--color-zinc-900))]\",\n className ?? \"\",\n ]\n .filter(Boolean)\n .join(\" \")}\n style={{ ...popStyle, ...style }}\n >\n {(cfg.label || active.query) && (\n <div className=\"flex items-center justify-between border-b border-zinc-100 bg-zinc-50 px-2 py-1 text-[10px] font-semibold uppercase tracking-wider text-zinc-500 dark:border-zinc-800 dark:bg-zinc-950\">\n <span>{cfg.label ?? labelForChar(active.char)}</span>\n {active.query && (\n <span className=\"font-mono text-[10px] normal-case tracking-normal text-zinc-400\">\n {active.char}\n {active.query}\n </span>\n )}\n </div>\n )}\n <ul className=\"max-h-60 overflow-y-auto\">\n {items.map((item, i) => {\n const renderer = cfg.render ?? ((it: unknown) => <span>{defaultKeyOf(it)}</span>);\n const active2 = i === cursor;\n const key = (cfg.keyOf ?? defaultKeyOf)(item);\n return (\n <li\n key={key}\n role=\"option\"\n aria-selected={active2}\n onMouseDown={(e) => {\n e.preventDefault();\n pickItem(item);\n }}\n onMouseEnter={() => setCursor(i)}\n className={[\n \"cursor-pointer px-2 py-1.5 text-[12px]\",\n active2\n ? \"bg-violet-100 dark:bg-violet-900/30\"\n : \"hover:bg-zinc-50 dark:hover:bg-zinc-800\",\n ].join(\" \")}\n >\n {renderer(item, active2)}\n </li>\n );\n })}\n </ul>\n </div>\n );\n}\n\nfunction labelForChar(ch: string): string {\n if (ch === \"/\") return \"Commands\";\n if (ch === \"@\") return \"Mentions\";\n if (ch === \"#\") return \"Tags\";\n if (ch === \":\") return \"Emoji\";\n return `Trigger ${ch}`;\n}\n\nfunction computePopoverStyle(\n anchor: DOMRect,\n placement: NonNullable<InputTagProps[\"placement\"]>,\n): CSSProperties {\n const offset = 4;\n switch (placement) {\n case \"bottom-right\":\n return { top: anchor.bottom + offset, right: window.innerWidth - anchor.right };\n case \"top-left\":\n return { bottom: window.innerHeight - anchor.top + offset, left: anchor.left };\n case \"top-right\":\n return { bottom: window.innerHeight - anchor.top + offset, right: window.innerWidth - anchor.right };\n case \"bottom-left\":\n default:\n return { top: anchor.bottom + offset, left: anchor.left };\n }\n}\n","import type { RefObject } from \"react\";\nimport type { InputTagAdapter } from \"./InputTag\";\n\n/**\n * Built-in DOM adapters. Each one wraps a familiar input element and\n * exposes the {@link InputTagAdapter} contract so `<InputTag>` can\n * attach to it. For non-DOM surfaces (code editor, sheet cell editor,\n * whiteboard sticky note), write your own — the contract is small.\n */\n\n/**\n * Get React's monkey-patched-aside native value setter on a DOM\n * element. Required when programmatically updating `value` on a\n * controlled input: React's intercepted setter would otherwise swallow\n * the change and the consumer's `onChange` would never fire.\n */\nfunction nativeValueSetter(el: HTMLInputElement | HTMLTextAreaElement): ((v: string) => void) | null {\n const proto = el instanceof HTMLTextAreaElement ? HTMLTextAreaElement.prototype : HTMLInputElement.prototype;\n const desc = Object.getOwnPropertyDescriptor(proto, \"value\");\n if (!desc?.set) return null;\n return desc.set.bind(el);\n}\n\nfunction replaceInValueElement(\n el: HTMLInputElement | HTMLTextAreaElement,\n start: number,\n end: number,\n replacement: string,\n): void {\n const current = el.value;\n const next = current.slice(0, start) + replacement + current.slice(end);\n const setter = nativeValueSetter(el);\n if (setter) {\n setter(next);\n } else {\n el.value = next;\n }\n // Dispatch a native `input` event so any controlled-component\n // onChange handler upstream gets the new value.\n el.dispatchEvent(new Event(\"input\", { bubbles: true }));\n // Place caret at the end of the inserted text.\n const caret = start + replacement.length;\n el.setSelectionRange(caret, caret);\n el.focus();\n}\n\nfunction valueElementAdapter(\n ref: RefObject<HTMLTextAreaElement | HTMLInputElement | null>,\n): InputTagAdapter {\n return {\n subscribe(fn) {\n const handler = () => {\n const el = ref.current;\n if (!el) return;\n fn({\n text: el.value,\n caretIndex: el.selectionStart ?? el.value.length,\n });\n };\n const el = ref.current;\n if (el) {\n el.addEventListener(\"input\", handler);\n el.addEventListener(\"click\", handler);\n el.addEventListener(\"keyup\", handler);\n el.addEventListener(\"focus\", handler);\n }\n return () => {\n const el2 = ref.current;\n if (el2) {\n el2.removeEventListener(\"input\", handler);\n el2.removeEventListener(\"click\", handler);\n el2.removeEventListener(\"keyup\", handler);\n el2.removeEventListener(\"focus\", handler);\n }\n };\n },\n replaceRange(start, end, replacement) {\n const el = ref.current;\n if (!el) return;\n replaceInValueElement(el, start, end, replacement);\n },\n getAnchorRect() {\n const el = ref.current;\n return el ? el.getBoundingClientRect() : null;\n },\n onKey(handler) {\n const fn = (e: KeyboardEvent) => {\n if (handler(e)) {\n e.preventDefault();\n e.stopPropagation();\n }\n };\n const el = ref.current;\n if (el) el.addEventListener(\"keydown\", fn as EventListener);\n return () => {\n const el2 = ref.current;\n if (el2) el2.removeEventListener(\"keydown\", fn as EventListener);\n };\n },\n };\n}\n\n/**\n * Adapter for a DOM `<textarea>`. Works whether the consumer manages\n * `value` via React state (controlled) or lets the DOM hold it\n * (uncontrolled) — `replaceRange` uses React's native value setter and\n * dispatches a native `input` event so the upstream onChange fires.\n */\nexport function textareaAdapter(\n ref: RefObject<HTMLTextAreaElement | null>,\n): InputTagAdapter {\n return valueElementAdapter(ref);\n}\n\n/** Adapter for a DOM `<input type=\"text|search|...\">`. */\nexport function inputAdapter(\n ref: RefObject<HTMLInputElement | null>,\n): InputTagAdapter {\n return valueElementAdapter(ref);\n}\n\n/**\n * Adapter for any `contenteditable` element. Operates on the element's\n * `textContent`; rich-text editors with their own internal model should\n * write a custom adapter that talks to that model instead.\n */\nexport function contentEditableAdapter(\n ref: RefObject<HTMLElement | null>,\n): InputTagAdapter {\n function caretIndex(el: HTMLElement): number {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return 0;\n const range = sel.getRangeAt(0).cloneRange();\n range.selectNodeContents(el);\n range.setEnd(sel.focusNode!, sel.focusOffset);\n return range.toString().length;\n }\n /**\n * Resolve an index into the element's visible text to a position inside the\n * text node that actually holds it. Returns null when the index is past the\n * end, or when there is no text node at all (an empty editable).\n *\n * This is the single walk that `setCaret` and `replaceRange` share. They used\n * to disagree: `setCaret` walked, `replaceRange` went through `textContent`.\n */\n function locate(\n el: HTMLElement,\n index: number,\n ): { node: Text; offset: number } | null {\n const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);\n let remaining = index;\n let node = walker.nextNode() as Text | null;\n while (node) {\n const len = node.textContent?.length ?? 0;\n if (remaining <= len) return { node, offset: remaining };\n remaining -= len;\n node = walker.nextNode() as Text | null;\n }\n return null;\n }\n function setCaret(el: HTMLElement, index: number): void {\n const sel = window.getSelection();\n if (!sel) return;\n const at = locate(el, index);\n const range = document.createRange();\n if (at) {\n range.setStart(at.node, at.offset);\n range.collapse(true);\n } else {\n // Past end (or nothing to walk): place at end.\n range.selectNodeContents(el);\n range.collapse(false);\n }\n sel.removeAllRanges();\n sel.addRange(range);\n }\n return {\n subscribe(fn) {\n const handler = () => {\n const el = ref.current;\n if (!el) return;\n fn({ text: el.textContent ?? \"\", caretIndex: caretIndex(el) });\n };\n const el = ref.current;\n if (el) {\n el.addEventListener(\"input\", handler);\n el.addEventListener(\"click\", handler);\n el.addEventListener(\"keyup\", handler);\n el.addEventListener(\"focus\", handler);\n }\n return () => {\n const el2 = ref.current;\n if (el2) {\n el2.removeEventListener(\"input\", handler);\n el2.removeEventListener(\"click\", handler);\n el2.removeEventListener(\"keyup\", handler);\n el2.removeEventListener(\"focus\", handler);\n }\n };\n },\n replaceRange(start, end, replacement) {\n const el = ref.current;\n if (!el) return;\n\n // Edit through a Range rather than rewriting `textContent`. Assigning\n // `textContent` destroys EVERY element child, so a host that renders a\n // resolved tag as a pill could only ever insert one: the next insert\n // flattened the first away. A Range touches nothing outside itself.\n const from = locate(el, start);\n const to = locate(el, end);\n const inserted = document.createTextNode(replacement);\n\n if (from && to) {\n const range = document.createRange();\n range.setStart(from.node, from.offset);\n range.setEnd(to.node, to.offset);\n range.deleteContents();\n range.insertNode(inserted);\n } else {\n // Past the end, or an empty editable with no text node to address.\n el.append(inserted);\n }\n\n // Anchor the caret on the node just written instead of re-deriving an\n // index: the text offsets have moved, and the node has not.\n const sel = window.getSelection();\n if (sel) {\n const after = document.createRange();\n after.setStart(inserted, inserted.length);\n after.collapse(true);\n sel.removeAllRanges();\n sel.addRange(after);\n }\n\n el.dispatchEvent(new Event(\"input\", { bubbles: true }));\n el.focus();\n },\n getAnchorRect() {\n const el = ref.current;\n return el ? el.getBoundingClientRect() : null;\n },\n onKey(handler) {\n const fn = (e: KeyboardEvent) => {\n if (handler(e)) {\n e.preventDefault();\n e.stopPropagation();\n }\n };\n const el = ref.current;\n if (el) el.addEventListener(\"keydown\", fn as EventListener);\n return () => {\n const el2 = ref.current;\n if (el2) el2.removeEventListener(\"keydown\", fn as EventListener);\n };\n },\n };\n}\n\n/**\n * Adapter for hosts that fully control the text state themselves. Use\n * this when you can't (or don't want to) let the DOM be the source of\n * truth — for code editors with internal state, sheet cell editors, or\n * any host that already has `value` + `onChange` and wants to reach the\n * picker programmatically.\n *\n * The host calls `notify({ text, caretIndex })` after every text or\n * caret change. `<InputTag>` calls `onReplaceRange` to write back.\n */\nexport type ControlledAdapterHandle = InputTagAdapter & {\n /** Push the latest text + caret to the picker. */\n notify: (state: { text: string; caretIndex: number }) => void;\n};\n\nexport function controlledAdapter(opts: {\n /** Element used as anchor + key target. Usually the visible input. */\n anchorRef: RefObject<HTMLElement | null>;\n /** Called when the picker writes back an insertion. */\n onReplaceRange: (start: number, end: number, replacement: string) => void;\n}): ControlledAdapterHandle {\n let listener: ((s: { text: string; caretIndex: number }) => void) | null = null;\n let keyHandler: ((e: KeyboardEvent) => boolean) | null = null;\n\n const installKey = () => {\n const el = opts.anchorRef.current;\n if (!el || !keyHandler) return () => {};\n const fn = (e: KeyboardEvent) => {\n if (keyHandler && keyHandler(e)) {\n e.preventDefault();\n e.stopPropagation();\n }\n };\n el.addEventListener(\"keydown\", fn);\n return () => el.removeEventListener(\"keydown\", fn);\n };\n\n return {\n notify(state) {\n listener?.(state);\n },\n subscribe(fn) {\n listener = fn;\n return () => {\n if (listener === fn) listener = null;\n };\n },\n replaceRange(start, end, replacement) {\n opts.onReplaceRange(start, end, replacement);\n },\n getAnchorRect() {\n const el = opts.anchorRef.current;\n return el ? el.getBoundingClientRect() : null;\n },\n onKey(handler) {\n keyHandler = handler;\n const uninstall = installKey();\n return () => {\n if (keyHandler === handler) keyHandler = null;\n uninstall();\n };\n },\n };\n}\n"]}
@@ -2,6 +2,7 @@
2
2
 
3
3
  var chunkTXTRTTG7_cjs = require('./chunk-TXTRTTG7.cjs');
4
4
  var chunkFQZE5N2N_cjs = require('./chunk-FQZE5N2N.cjs');
5
+ var chunk6V44RRSB_cjs = require('./chunk-6V44RRSB.cjs');
5
6
  var chunkTI7D4QDM_cjs = require('./chunk-TI7D4QDM.cjs');
6
7
  var chunkOUYC6EIL_cjs = require('./chunk-OUYC6EIL.cjs');
7
8
  var chunkSNHU2AI4_cjs = require('./chunk-SNHU2AI4.cjs');
@@ -172,6 +173,7 @@ function CommandRoot({
172
173
  e.preventDefault();
173
174
  setActiveIndex(activeIndex > 0 ? activeIndex - 1 : items.length - 1);
174
175
  } else if (e.key === "Enter") {
176
+ if (chunk6V44RRSB_cjs.isImeComposing(e)) return;
175
177
  if (e.target?.getAttribute("role") === "option") return;
176
178
  const pick = items[activeIndex] ?? items[0];
177
179
  e.preventDefault();
@@ -260,5 +262,5 @@ var Command = Object.assign(CommandRoot, {
260
262
 
261
263
  exports.Command = Command;
262
264
  exports.useCommand = useCommand;
263
- //# sourceMappingURL=chunk-UJRMY54A.cjs.map
264
- //# sourceMappingURL=chunk-UJRMY54A.cjs.map
265
+ //# sourceMappingURL=chunk-3QCAOD2W.cjs.map
266
+ //# sourceMappingURL=chunk-3QCAOD2W.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/Command/Command.context.ts","../src/components/Command/CommandInput.tsx","../src/components/Command/CommandList.tsx","../src/components/Command/CommandItem.tsx","../src/components/Command/CommandGroup.tsx","../src/components/Command/CommandEmpty.tsx","../src/components/Command/Command.tsx"],"names":["createContext","useContext","jsxs","jsx","Search","cn","useId","useControllableState","useState","useRef","useCallback","useEscapeKey","useFocusTrap","useEffect","isImeComposing","useLayoutEffect","useAnimation","useMemo","Portal"],"mappings":";;;;;;;;;;;;;AAGO,IAAM,cAAA,GAAiBA,oBAA0C,IAAI,CAAA;AAErE,SAAS,UAAA,GAAkC;AAChD,EAAA,MAAM,GAAA,GAAMC,iBAAW,cAAc,CAAA;AACrC,EAAA,IAAI,CAAC,GAAA,EAAK;AACR,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AACA,EAAA,OAAO,GAAA;AACT;ACRO,SAAS,YAAA,CAAa;AAAA,EAC3B,WAAA,GAAc,6BAAA;AAAA,EACd;AACF,CAAA,EAAsB;AACpB,EAAA,MAAM,EAAE,KAAA,EAAO,QAAA,EAAU,MAAA,KAAW,UAAA,EAAW;AAE/C,EAAA,uBACEC,eAAA,CAAC,KAAA,EAAA,EAAI,gCAAA,EAA+B,EAAA,EAAG,WAAU,6JAAA,EAC/C,QAAA,EAAA;AAAA,oBAAAC,cAAA,CAACC,kBAAA,EAAA,EAAO,IAAA,EAAM,EAAA,EAAI,SAAA,EAAU,wBAAA,EAAyB,CAAA;AAAA,oBACrDD,cAAA;AAAA,MAAC,OAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,MAAA;AAAA,QAGL,IAAA,EAAK,UAAA;AAAA,QACL,eAAA,EAAc,MAAA;AAAA,QACd,eAAA,EAAe,MAAA;AAAA,QACf,mBAAA,EAAkB,MAAA;AAAA,QAClB,KAAA,EAAO,KAAA;AAAA,QACP,UAAU,CAAC,CAAA,KAAM,QAAA,CAAS,CAAA,CAAE,OAAO,KAAK,CAAA;AAAA,QACxC,WAAA;AAAA,QACA,SAAA,EAAWE,oBAAA;AAAA,UACT,gFAAA;AAAA,UACA;AAAA,SACF;AAAA,QACA,SAAA,EAAS;AAAA;AAAA;AACX,GAAA,EACF,CAAA;AAEJ;AAEA,YAAA,CAAa,WAAA,GAAc,cAAA;AC/BpB,SAAS,WAAA,CAAY,EAAE,QAAA,EAAU,SAAA,EAAU,EAAqB;AACrE,EAAA,MAAM,EAAE,MAAA,EAAO,GAAI,UAAA,EAAW;AAE9B,EAAA,uBACEF,cAAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,EAAA,EAAI,MAAA;AAAA,MACJ,+BAAA,EAA8B,EAAA;AAAA,MAC9B,IAAA,EAAK,SAAA;AAAA,MACL,SAAA,EAAWE,oBAAA,CAAG,8BAAA,EAAgC,SAAS,CAAA;AAAA,MAEtD;AAAA;AAAA,GACH;AAEJ;AAEA,WAAA,CAAY,WAAA,GAAc,aAAA;ACdnB,SAAS,WAAA,CAAY;AAAA,EAC1B,QAAA;AAAA,EACA,KAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAA,EAAqB;AACnB,EAAA,MAAM,EAAE,KAAA,EAAO,KAAA,EAAO,YAAA,EAAc,cAAA,KAAmB,UAAA,EAAW;AAElE,EAAA,MAAM,KAAKC,WAAA,EAAM;AAGjB,EAAA,MAAM,IAAA,GAAO,KAAA,KAAU,OAAO,QAAA,KAAa,WAAW,QAAA,GAAW,EAAA,CAAA;AACjE,EAAA,IAAI,YAAA,IAAgB,KAAA,IAAS,CAAC,IAAA,CAAK,WAAA,GAAc,QAAA,CAAS,KAAA,CAAM,WAAA,EAAa,CAAA,EAAG;AAC9E,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,uBACEH,cAAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,EAAA;AAAA,MACA,+BAAA,EAA8B,EAAA;AAAA,MAC9B,IAAA,EAAK,QAAA;AAAA,MACL,IAAA,EAAK,QAAA;AAAA,MAGL,eAAA,EAAe,KAAA;AAAA,MAEf,QAAA,EAAU,EAAA;AAAA,MACV,YAAA,EAAc,CAAC,CAAA,KAAM;AACnB,QAAA,MAAM,UAAU,CAAA,CAAE,aAAA,CACf,QAAQ,4BAA4B,CAAA,EACnC,iBAAiB,iBAAiB,CAAA;AACtC,QAAA,IAAI,OAAA,iBAAwB,KAAA,CAAM,IAAA,CAAK,OAAO,CAAA,CAAE,OAAA,CAAQ,CAAA,CAAE,aAAa,CAAC,CAAA;AAAA,MAC1E,CAAA;AAAA,MACA,SAAA,EAAWE,oBAAA;AAAA,QACT,mFAAA;AAAA,QACA,2aAAA;AAAA,QACA;AAAA,OACF;AAAA,MACA,SAAS,MAAM;AACb,QAAA,QAAA,IAAW;AACX,QAAA,KAAA,EAAM;AAAA,MACR,CAAA;AAAA,MAEC;AAAA;AAAA,GACH;AAEJ;AAEA,WAAA,CAAY,WAAA,GAAc,aAAA;AClDnB,SAAS,YAAA,CAAa;AAAA,EAC3B,QAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAA,EAAsB;AACpB,EAAA,uBACEH,eAAAA,CAAC,KAAA,EAAA,EAAI,gCAAA,EAA+B,EAAA,EAAG,IAAA,EAAK,OAAA,EAAQ,SAAA,EAAWG,oBAAA,CAAG,MAAA,EAAQ,SAAS,CAAA,EAChF,QAAA,EAAA;AAAA,IAAA,OAAA,oBACCF,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,iDACZ,QAAA,EAAA,OAAA,EACH,CAAA;AAAA,IAED;AAAA,GAAA,EACH,CAAA;AAEJ;AAEA,YAAA,CAAa,WAAA,GAAc,cAAA;ACjBpB,SAAS,YAAA,CAAa;AAAA,EAC3B,QAAA,GAAW,mBAAA;AAAA,EACX;AACF,CAAA,EAAsB;AACpB,EAAA,uBACEA,cAAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,gCAAA,EAA+B,EAAA;AAAA,MAC/B,SAAA,EAAWE,oBAAA;AAAA,QACT,0JAAA;AAAA,QACA;AAAA,OACF;AAAA,MAEC;AAAA;AAAA,GACH;AAEJ;AAEA,YAAA,CAAa,WAAA,GAAc,cAAA;ACI3B,SAAS,WAAA,CAAY;AAAA,EACnB,QAAA;AAAA,EACA,IAAA;AAAA,EACA,OAAA;AAAA,EACA,SAAA;AAAA,EACA,YAAA,GAAe,IAAA;AAAA,EACf,KAAA,EAAO,eAAA;AAAA,EACP;AACF,CAAA,EAAiB;AACf,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,IAAIE,sCAAA,CAAqB,eAAA,EAAiB,IAAI,aAAa,CAAA;AACjF,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAIC,eAAS,EAAE,CAAA;AACjD,EAAA,MAAM,QAAA,GAAWC,aAAuB,IAAI,CAAA;AAC5C,EAAA,MAAM,SAASH,WAAAA,EAAM;AAErB,EAAA,MAAM,KAAA,GAAQI,kBAAY,MAAM;AAC9B,IAAA,OAAA,EAAQ;AACR,IAAA,QAAA,CAAS,EAAE,CAAA;AACX,IAAA,cAAA,CAAe,EAAE,CAAA;AAAA,EACnB,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AAEZ,EAAAC,8BAAA,CAAa,OAAO,IAAI,CAAA;AACxB,EAAAC,8BAAA,CAAa,UAAU,IAAI,CAAA;AAG3B,EAAAC,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,IAAA,EAAM;AACR,MAAA,MAAM,QAAA,GAAW,QAAA,CAAS,IAAA,CAAK,KAAA,CAAM,QAAA;AACrC,MAAA,QAAA,CAAS,IAAA,CAAK,MAAM,QAAA,GAAW,QAAA;AAC/B,MAAA,OAAO,MAAM;AACX,QAAA,QAAA,CAAS,IAAA,CAAK,MAAM,QAAA,GAAW,QAAA;AAAA,MACjC,CAAA;AAAA,IACF;AAAA,EACF,CAAA,EAAG,CAAC,IAAI,CAAC,CAAA;AAWT,EAAAA,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,IAAA,EAAM;AAEX,IAAA,MAAM,aAAA,GAAgB,CAAC,CAAA,KAAqB;AAC1C,MAAA,MAAM,KAAA,GAAQ,SAAS,OAAA,EAAS,gBAAA;AAAA,QAC9B;AAAA,OACF;AACA,MAAA,IAAI,CAAC,OAAO,MAAA,EAAQ;AAEpB,MAAA,IAAI,CAAA,CAAE,QAAQ,WAAA,EAAa;AACzB,QAAA,CAAA,CAAE,cAAA,EAAe;AACjB,QAAA,cAAA,CAAe,cAAc,KAAA,CAAM,MAAA,GAAS,CAAA,GAAI,WAAA,GAAc,IAAI,CAAC,CAAA;AAAA,MACrE,CAAA,MAAA,IAAW,CAAA,CAAE,GAAA,KAAQ,SAAA,EAAW;AAC9B,QAAA,CAAA,CAAE,cAAA,EAAe;AACjB,QAAA,cAAA,CAAe,cAAc,CAAA,GAAI,WAAA,GAAc,CAAA,GAAI,KAAA,CAAM,SAAS,CAAC,CAAA;AAAA,MACrE,CAAA,MAAA,IAAW,CAAA,CAAE,GAAA,KAAQ,OAAA,EAAS;AAC5B,QAAA,IAAIC,gCAAA,CAAe,CAAC,CAAA,EAAG;AAGvB,QAAA,IAAK,CAAA,CAAE,MAAA,EAA+B,YAAA,CAAa,MAAM,MAAM,QAAA,EAAU;AACzE,QAAA,MAAM,IAAA,GAAO,KAAA,CAAM,WAAW,CAAA,IAAK,MAAM,CAAC,CAAA;AAC1C,QAAA,CAAA,CAAE,cAAA,EAAe;AACjB,QAAA,IAAA,CAAK,KAAA,EAAM;AAAA,MACb;AAAA,IACF,CAAA;AAEA,IAAA,QAAA,CAAS,gBAAA,CAAiB,WAAW,aAAa,CAAA;AAClD,IAAA,OAAO,MAAM,QAAA,CAAS,mBAAA,CAAoB,SAAA,EAAW,aAAa,CAAA;AAAA,EACpE,CAAA,EAAG,CAAC,IAAA,EAAM,WAAW,CAAC,CAAA;AAOtB,EAAAC,qBAAA,CAAgB,MAAM;AACpB,IAAA,MAAM,QAAQ,QAAA,CAAS,OAAA;AACvB,IAAA,IAAI,CAAC,KAAA,EAAO;AAEZ,IAAA,MAAM,QAAQ,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,gBAAA,CAA8B,iBAAiB,CAAC,CAAA;AAC/E,IAAA,MAAM,MAAA,GAAS,MAAM,WAAW,CAAA;AAChC,IAAA,KAAA,CAAM,OAAA,CAAQ,CAAC,IAAA,KAAS;AACtB,MAAA,MAAM,KAAK,IAAA,KAAS,MAAA;AACpB,MAAA,IAAA,CAAK,YAAA,CAAa,eAAA,EAAiB,EAAA,GAAK,MAAA,GAAS,OAAO,CAAA;AACxD,MAAA,IAAI,EAAA,EAAI,IAAA,CAAK,YAAA,CAAa,aAAA,EAAe,EAAE,CAAA;AAAA,WACtC,IAAA,CAAK,gBAAgB,aAAa,CAAA;AAAA,IACzC,CAAC,CAAA;AAED,IAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,aAAA,CAAgC,wCAAwC,CAAA;AAC5F,IAAA,IAAI,QAAQ,EAAA,EAAI,KAAA,EAAO,YAAA,CAAa,uBAAA,EAAyB,OAAO,EAAE,CAAA;AAAA,SACjE,KAAA,EAAO,gBAAgB,uBAAuB,CAAA;AACnD,IAAA,MAAA,EAAQ,cAAA,GAAiB,EAAE,KAAA,EAAO,SAAA,EAAW,CAAA;AAAA,EAC/C,CAAC,CAAA;AAGD,EAAA,MAAM,WAAA,GAAcL,iBAAA;AAAA,IAClB,CAAC,IAAA,KAAiB;AAChB,MAAA,QAAA,CAAS,IAAI,CAAA;AACb,MAAA,cAAA,CAAe,EAAE,CAAA;AAAA,IACnB,CAAA;AAAA,IACA,CAAC,QAAQ;AAAA,GACX;AAEA,EAAA,MAAM,EAAE,OAAA,EAAS,SAAA,EAAW,WAAW,GAAA,EAAK,OAAA,KAAYM,8BAAA,CAAa;AAAA,IACnE,IAAA;AAAA,IACA,UAAA,EAAY,gBAAA;AAAA,IACZ,SAAA,EAAW;AAAA,GACZ,CAAA;AAED,EAAA,MAAM,GAAA,GAAMC,aAAA;AAAA,IACV,OAAO;AAAA,MACL,IAAA;AAAA,MACA,KAAA;AAAA,MACA,KAAA;AAAA,MACA,QAAA,EAAU,WAAA;AAAA,MACV,WAAA;AAAA,MACA,cAAA;AAAA,MACA,YAAA;AAAA,MACA;AAAA,KACF,CAAA;AAAA,IACA,CAAC,IAAA,EAAM,KAAA,EAAO,OAAO,WAAA,EAAa,WAAA,EAAa,cAAc,MAAM;AAAA,GACrE;AAEA,EAAA,IAAI,CAAC,SAAS,OAAO,IAAA;AAErB,EAAA,uBACEd,cAAAA,CAAC,cAAA,CAAe,QAAA,EAAf,EAAwB,KAAA,EAAO,GAAA,EAC9B,QAAA,kBAAAA,cAAAA,CAACe,wBAAA,EAAA,EACC,QAAA,kBAAAhB,eAAAA,CAAC,KAAA,EAAA,EAAI,WAAU,8DAAA,EACb,QAAA,EAAA;AAAA,oBAAAC,cAAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAU,+CAAA;AAAA,QACV,OAAA,EAAS,KAAA;AAAA,QACT,aAAA,EAAY;AAAA;AAAA,KACd;AAAA,oBACAA,cAAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAA,EAAK,CAAC,IAAA,KAAS;AACb,UAAA,QAAA,CAAS,OAAA,GAAU,IAAA;AACnB,UAAC,QAAuD,OAAA,GACtD,IAAA;AAAA,QACJ,CAAA;AAAA,QACA,0BAAA,EAAyB,EAAA;AAAA,QACzB,SAAA,EAAWE,oBAAA;AAAA,UACT,uTAAA;AAAA,UACA,SAAA;AAAA,UACA;AAAA,SACF;AAAA,QAEC;AAAA;AAAA;AACH,GAAA,EACF,GACF,CAAA,EACF,CAAA;AAEJ;AAEO,IAAM,OAAA,GAAU,MAAA,CAAO,MAAA,CAAO,WAAA,EAAa;AAAA,EAChD,KAAA,EAAO,YAAA;AAAA,EACP,IAAA,EAAM,WAAA;AAAA,EACN,IAAA,EAAM,WAAA;AAAA,EACN,KAAA,EAAO,YAAA;AAAA,EACP,KAAA,EAAO;AACT,CAAC","file":"chunk-3QCAOD2W.cjs","sourcesContent":["import { createContext, useContext } from \"react\";\nimport type { CommandContextValue } from \"./Command.types\";\n\nexport const CommandContext = createContext<CommandContextValue | null>(null);\n\nexport function useCommand(): CommandContextValue {\n const ctx = useContext(CommandContext);\n if (!ctx) {\n throw new Error(\n \"Command compound components must be used within <Command>\",\n );\n }\n return ctx;\n}\n","import { Search } from \"lucide-react\";\nimport { cn } from \"../../utils/cn\";\nimport { useCommand } from \"./Command.context\";\nimport type { CommandInputProps } from \"./Command.types\";\n\nexport function CommandInput({\n placeholder = \"Type a command or search...\",\n className,\n}: CommandInputProps) {\n const { query, setQuery, listId } = useCommand();\n\n return (\n <div data-react-fancy-command-input=\"\" className=\"flex items-center border-b border-[color:var(--fancy-border,var(--color-zinc-200))] px-4 dark:border-[color:var(--fancy-border-dark,var(--color-zinc-700))]\">\n <Search size={16} className=\"shrink-0 text-zinc-400\" />\n <input\n type=\"text\"\n // A combobox: focus stays here while the arrows move the active option,\n // which Command announces through aria-activedescendant.\n role=\"combobox\"\n aria-expanded=\"true\"\n aria-controls={listId}\n aria-autocomplete=\"list\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n placeholder={placeholder}\n className={cn(\n \"flex-1 bg-transparent px-3 py-3 text-sm outline-none placeholder:text-zinc-400\",\n className,\n )}\n autoFocus\n />\n </div>\n );\n}\n\nCommandInput.displayName = \"CommandInput\";\n","import { cn } from \"../../utils/cn\";\nimport { useCommand } from \"./Command.context\";\nimport type { CommandListProps } from \"./Command.types\";\n\nexport function CommandList({ children, className }: CommandListProps) {\n const { listId } = useCommand();\n\n return (\n <div\n id={listId}\n data-react-fancy-command-list=\"\"\n role=\"listbox\"\n className={cn(\"max-h-72 overflow-y-auto p-2\", className)}\n >\n {children}\n </div>\n );\n}\n\nCommandList.displayName = \"CommandList\";\n","import { useId } from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { useCommand } from \"./Command.context\";\nimport type { CommandItemProps } from \"./Command.types\";\n\nexport function CommandItem({\n children,\n value,\n onSelect,\n className,\n}: CommandItemProps) {\n const { query, close, shouldFilter, setActiveIndex } = useCommand();\n // Called before the filter's early return, so the hook order never changes.\n const id = useId();\n\n // Filter by query — unless the caller filters for itself (`shouldFilter={false}`).\n const text = value ?? (typeof children === \"string\" ? children : \"\");\n if (shouldFilter && query && !text.toLowerCase().includes(query.toLowerCase())) {\n return null;\n }\n\n return (\n <button\n id={id}\n data-react-fancy-command-item=\"\"\n type=\"button\"\n role=\"option\"\n // Marked active by Command itself (aria-selected + data-active), since an\n // item cannot know its own position among the rendered options.\n aria-selected={false}\n // Keyboard focus stays in the input; the items are reached with the arrows.\n tabIndex={-1}\n onMouseEnter={(e) => {\n const options = e.currentTarget\n .closest(\"[data-react-fancy-command]\")\n ?.querySelectorAll('[role=\"option\"]');\n if (options) setActiveIndex(Array.from(options).indexOf(e.currentTarget));\n }}\n className={cn(\n \"flex w-full items-center rounded-lg px-3 py-2 text-left text-sm transition-colors\",\n \"text-[color:var(--fancy-text-soft,var(--color-zinc-700))] hover:bg-[color:var(--fancy-surface-muted,var(--color-zinc-100))] data-[active]:bg-[color:var(--fancy-surface-muted,var(--color-zinc-100))] dark:text-[color:var(--fancy-text-soft-dark,var(--color-zinc-300))] dark:hover:bg-[color:var(--fancy-surface-muted-dark,var(--color-zinc-800))] dark:data-[active]:bg-[color:var(--fancy-surface-muted-dark,var(--color-zinc-800))]\",\n className,\n )}\n onClick={() => {\n onSelect?.();\n close();\n }}\n >\n {children}\n </button>\n );\n}\n\nCommandItem.displayName = \"CommandItem\";\n","import { cn } from \"../../utils/cn\";\nimport type { CommandGroupProps } from \"./Command.types\";\n\nexport function CommandGroup({\n children,\n heading,\n className,\n}: CommandGroupProps) {\n return (\n <div data-react-fancy-command-group=\"\" role=\"group\" className={cn(\"py-1\", className)}>\n {heading && (\n <div className=\"px-3 py-1.5 text-xs font-medium text-zinc-400\">\n {heading}\n </div>\n )}\n {children}\n </div>\n );\n}\n\nCommandGroup.displayName = \"CommandGroup\";\n","import { cn } from \"../../utils/cn\";\nimport type { CommandEmptyProps } from \"./Command.types\";\n\nexport function CommandEmpty({\n children = \"No results found.\",\n className,\n}: CommandEmptyProps) {\n return (\n <div\n data-react-fancy-command-empty=\"\"\n className={cn(\n \"py-6 text-center text-sm text-[color:var(--fancy-text-muted,var(--color-zinc-500))] dark:text-[color:var(--fancy-text-muted-dark,var(--color-zinc-400))]\",\n className,\n )}\n >\n {children}\n </div>\n );\n}\n\nCommandEmpty.displayName = \"CommandEmpty\";\n","import {\n useCallback,\n useEffect,\n useId,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { isImeComposing } from \"../../utils/ime\";\nimport { Portal } from \"../Portal\";\nimport { CommandContext } from \"./Command.context\";\nimport { CommandInput } from \"./CommandInput\";\nimport { CommandList } from \"./CommandList\";\nimport { CommandItem } from \"./CommandItem\";\nimport { CommandGroup } from \"./CommandGroup\";\nimport { CommandEmpty } from \"./CommandEmpty\";\nimport { useFocusTrap } from \"../../hooks/use-focus-trap\";\nimport { useEscapeKey } from \"../../hooks/use-escape-key\";\nimport { useAnimation } from \"../../hooks/use-animation\";\nimport { useControllableState } from \"../../hooks/use-controllable-state\";\nimport type { CommandProps } from \"./Command.types\";\n\nfunction CommandRoot({\n children,\n open,\n onClose,\n className,\n shouldFilter = true,\n query: controlledQuery,\n onQueryChange,\n}: CommandProps) {\n const [query, setQuery] = useControllableState(controlledQuery, \"\", onQueryChange);\n const [activeIndex, setActiveIndex] = useState(-1);\n const panelRef = useRef<HTMLDivElement>(null);\n const listId = useId();\n\n const close = useCallback(() => {\n onClose();\n setQuery(\"\");\n setActiveIndex(-1);\n }, [onClose]);\n\n useEscapeKey(close, open);\n useFocusTrap(panelRef, open);\n\n // Cmd+K global shortcut is handled by the consumer\n useEffect(() => {\n if (open) {\n const original = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n return () => {\n document.body.style.overflow = original;\n };\n }\n }, [open]);\n\n /*\n * Keyboard navigation, as a combobox: the arrows move the ACTIVE item while\n * focus stays in the input (announced through aria-activedescendant), and\n * Enter picks the active item — or the first visible one when none is active.\n *\n * Focus used to move onto the items, and Enter was handled nowhere, so typing\n * a query and pressing Enter did nothing: only a focused item took Enter, as a\n * native click. Found by Genie 2's real-window test.\n */\n useEffect(() => {\n if (!open) return;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n const items = panelRef.current?.querySelectorAll<HTMLElement>(\n '[role=\"option\"]',\n );\n if (!items?.length) return;\n\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n setActiveIndex(activeIndex < items.length - 1 ? activeIndex + 1 : 0);\n } else if (e.key === \"ArrowUp\") {\n e.preventDefault();\n setActiveIndex(activeIndex > 0 ? activeIndex - 1 : items.length - 1);\n } else if (e.key === \"Enter\") {\n if (isImeComposing(e)) return;\n // A focused item takes Enter natively, as a click; picking here as well\n // would select it twice.\n if ((e.target as HTMLElement | null)?.getAttribute(\"role\") === \"option\") return;\n const pick = items[activeIndex] ?? items[0];\n e.preventDefault();\n pick.click();\n }\n };\n\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [open, activeIndex]);\n\n /*\n * Mark the active item and point the input at it. Done on the DOM after each\n * render because an item cannot know its own index — that is its position\n * among the options currently rendered, which filtering changes.\n */\n useLayoutEffect(() => {\n const panel = panelRef.current;\n if (!panel) return;\n\n const items = Array.from(panel.querySelectorAll<HTMLElement>('[role=\"option\"]'));\n const active = items[activeIndex];\n items.forEach((item) => {\n const on = item === active;\n item.setAttribute(\"aria-selected\", on ? \"true\" : \"false\");\n if (on) item.setAttribute(\"data-active\", \"\");\n else item.removeAttribute(\"data-active\");\n });\n\n const input = panel.querySelector<HTMLInputElement>(\"[data-react-fancy-command-input] input\");\n if (active?.id) input?.setAttribute(\"aria-activedescendant\", active.id);\n else input?.removeAttribute(\"aria-activedescendant\");\n active?.scrollIntoView?.({ block: \"nearest\" });\n });\n\n // A new query is a new list: nothing in it is active yet, so Enter picks the first match.\n const changeQuery = useCallback(\n (next: string) => {\n setQuery(next);\n setActiveIndex(-1);\n },\n [setQuery],\n );\n\n const { mounted, className: animClass, ref: animRef } = useAnimation({\n open,\n enterClass: \"fancy-slide-up\",\n exitClass: \"fancy-fade-out\",\n });\n\n const ctx = useMemo(\n () => ({\n open,\n close,\n query,\n setQuery: changeQuery,\n activeIndex,\n setActiveIndex,\n shouldFilter,\n listId,\n }),\n [open, close, query, changeQuery, activeIndex, shouldFilter, listId],\n );\n\n if (!mounted) return null;\n\n return (\n <CommandContext.Provider value={ctx}>\n <Portal>\n <div className=\"fixed inset-0 z-50 flex items-start justify-center pt-[20vh]\">\n <div\n className=\"absolute inset-0 bg-black/50 backdrop-blur-sm\"\n onClick={close}\n aria-hidden=\"true\"\n />\n <div\n ref={(node) => {\n panelRef.current = node;\n (animRef as React.MutableRefObject<HTMLElement | null>).current =\n node;\n }}\n data-react-fancy-command=\"\"\n className={cn(\n \"relative w-full max-w-lg overflow-hidden rounded-2xl border border-[color:var(--fancy-border,var(--color-zinc-200))] bg-[color:var(--fancy-surface,var(--color-white))] shadow-2xl dark:border-[color:var(--fancy-border-dark,var(--color-zinc-700))] dark:bg-[color:var(--fancy-surface-dark,var(--color-zinc-900))]\",\n animClass,\n className,\n )}\n >\n {children}\n </div>\n </div>\n </Portal>\n </CommandContext.Provider>\n );\n}\n\nexport const Command = Object.assign(CommandRoot, {\n Input: CommandInput,\n List: CommandList,\n Item: CommandItem,\n Group: CommandGroup,\n Empty: CommandEmpty,\n});\n"]}
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
 
3
+ var chunk6V44RRSB_cjs = require('./chunk-6V44RRSB.cjs');
3
4
  var chunkSNHU2AI4_cjs = require('./chunk-SNHU2AI4.cjs');
4
5
  var chunkZU5Q77OT_cjs = require('./chunk-ZU5Q77OT.cjs');
5
6
  var react = require('react');
@@ -41,6 +42,7 @@ var Pillbox = react.forwardRef(
41
42
  );
42
43
  const handleKeyDown = (e) => {
43
44
  if (e.key === "Enter") {
45
+ if (chunk6V44RRSB_cjs.isImeComposing(e)) return;
44
46
  e.preventDefault();
45
47
  addItem(input);
46
48
  } else if (e.key === "Backspace" && !input && items.length > 0) {
@@ -103,5 +105,5 @@ var Pillbox = react.forwardRef(
103
105
  Pillbox.displayName = "Pillbox";
104
106
 
105
107
  exports.Pillbox = Pillbox;
106
- //# sourceMappingURL=chunk-KSU6RYWU.cjs.map
107
- //# sourceMappingURL=chunk-KSU6RYWU.cjs.map
108
+ //# sourceMappingURL=chunk-3T3LBIQA.cjs.map
109
+ //# sourceMappingURL=chunk-3T3LBIQA.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/Pillbox/Pillbox.tsx"],"names":["forwardRef","Pillbox","useControllableState","useState","useRef","useCallback","isImeComposing","jsxs","cn","jsx","X"],"mappings":"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","file":"chunk-3T3LBIQA.cjs","sourcesContent":["import { forwardRef, useCallback, useRef, useState } from \"react\";\nimport { X } from \"lucide-react\";\nimport { cn } from \"../../utils/cn\";\nimport { isImeComposing } from \"../../utils/ime\";\nimport { useControllableState } from \"../../hooks/use-controllable-state\";\nimport type { PillboxProps } from \"./Pillbox.types\";\n\nexport const Pillbox = forwardRef<HTMLDivElement, PillboxProps>(\n function Pillbox(\n {\n value: controlledValue,\n defaultValue = [],\n onChange,\n placeholder = \"Type and press Enter...\",\n maxItems,\n disabled = false,\n className,\n },\n ref,\n ) {\n const [items, setItems] = useControllableState(\n controlledValue,\n defaultValue,\n onChange,\n );\n const [input, setInput] = useState(\"\");\n const inputRef = useRef<HTMLInputElement>(null);\n\n const addItem = useCallback(\n (text: string) => {\n const trimmed = text.trim();\n if (!trimmed || items.includes(trimmed)) return;\n if (maxItems && items.length >= maxItems) return;\n setItems([...items, trimmed]);\n setInput(\"\");\n },\n [items, setItems, maxItems],\n );\n\n const removeItem = useCallback(\n (index: number) => {\n setItems(items.filter((_, i) => i !== index));\n },\n [items, setItems],\n );\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"Enter\") {\n if (isImeComposing(e)) return;\n e.preventDefault();\n addItem(input);\n } else if (e.key === \"Backspace\" && !input && items.length > 0) {\n removeItem(items.length - 1);\n }\n };\n\n return (\n <div\n data-react-fancy-pillbox=\"\"\n ref={ref}\n className={cn(\n \"flex flex-wrap items-center gap-1.5 rounded-lg border border-[color:var(--fancy-border,var(--color-zinc-200))] bg-[color:var(--fancy-input,var(--color-white))] px-3 py-2 transition-[border-color,box-shadow] duration-150 focus-within:border-[color:var(--fancy-focus,var(--color-blue-500))] focus-within:ring-2 focus-within:ring-[color:var(--fancy-focus,var(--color-blue-500))]/40 dark:border-[color:var(--fancy-border-dark,var(--color-zinc-700))] dark:bg-[color:var(--fancy-input-dark,#1e1e24)] dark:text-zinc-100 dark:focus-within:border-[color:var(--fancy-focus-dark,var(--color-blue-400))] dark:focus-within:ring-[color:var(--fancy-focus-dark,var(--color-blue-400))]/20\",\n disabled && \"cursor-not-allowed opacity-50\",\n className,\n )}\n onClick={() => inputRef.current?.focus()}\n >\n {items.map((item, i) => (\n <span\n key={`${item}-${i}`}\n className=\"inline-flex items-center gap-1 rounded-md bg-[color:var(--fancy-surface-muted,var(--color-zinc-100))] px-2 py-0.5 text-sm dark:bg-[color:var(--fancy-surface-muted-dark,var(--color-zinc-800))]\"\n >\n {item}\n {!disabled && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n removeItem(i);\n }}\n className=\"text-zinc-400 hover:text-zinc-600 dark:hover:text-zinc-300\"\n aria-label={`Remove ${item}`}\n >\n <X size={12} />\n </button>\n )}\n </span>\n ))}\n <input\n ref={inputRef}\n type=\"text\"\n value={input}\n onChange={(e) => setInput(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={items.length === 0 ? placeholder : \"\"}\n disabled={disabled}\n className=\"min-w-[80px] flex-1 bg-transparent text-sm outline-none placeholder:text-zinc-400\"\n />\n </div>\n );\n },\n);\n\nPillbox.displayName = \"Pillbox\";\n"]}
@@ -2,7 +2,7 @@
2
2
 
3
3
  var chunkVQJ5LJJH_cjs = require('./chunk-VQJ5LJJH.cjs');
4
4
  var chunk4GOOSZEK_cjs = require('./chunk-4GOOSZEK.cjs');
5
- var chunkKGJ2ORY6_cjs = require('./chunk-KGJ2ORY6.cjs');
5
+ var chunkR3EJNGJV_cjs = require('./chunk-R3EJNGJV.cjs');
6
6
  var chunkG7227RTY_cjs = require('./chunk-G7227RTY.cjs');
7
7
  var chunkL3V3BYVS_cjs = require('./chunk-L3V3BYVS.cjs');
8
8
  var chunk3U7PUZLI_cjs = require('./chunk-3U7PUZLI.cjs');
@@ -158,7 +158,7 @@ function EditorContent({ className, maxHeight: maxHeightProp, sourceClassName })
158
158
  }
159
159
  }, [contentRef, _initialHtml, showSource]);
160
160
  const extClasses = react.useMemo(
161
- () => chunkKGJ2ORY6_cjs.extensionEditorClasses(extensions),
161
+ () => chunkR3EJNGJV_cjs.extensionEditorClasses(extensions),
162
162
  [extensions]
163
163
  );
164
164
  if (showSource) {
@@ -190,7 +190,7 @@ function EditorContent({ className, maxHeight: maxHeightProp, sourceClassName })
190
190
  className: chunkZU5Q77OT_cjs.cn(
191
191
  "min-h-[120px] flex-auto overflow-y-auto px-4 py-3 text-sm outline-none",
192
192
  "focus:outline-none",
193
- chunkKGJ2ORY6_cjs.proseClasses,
193
+ chunkR3EJNGJV_cjs.proseClasses,
194
194
  extClasses,
195
195
  "empty:before:content-[attr(data-placeholder)] empty:before:text-zinc-400 empty:before:pointer-events-none",
196
196
  className
@@ -202,9 +202,9 @@ EditorContent.displayName = "EditorContent";
202
202
  function toHtml(value, outputFormat, unsafe, valueFormat = "auto") {
203
203
  if (!value) return { html: "", source: null };
204
204
  const sanitize = (html) => unsafe ? html : chunk3U7PUZLI_cjs.sanitizeHtml(html);
205
- const format = valueFormat !== "auto" ? valueFormat : outputFormat === "html" ? "html" : chunkKGJ2ORY6_cjs.detectFormat(value);
205
+ const format = valueFormat !== "auto" ? valueFormat : outputFormat === "html" ? "html" : chunkR3EJNGJV_cjs.detectFormat(value);
206
206
  if (format === "html") return { html: sanitize(value), source: null };
207
- if (outputFormat === "markdown") return chunkKGJ2ORY6_cjs.markdownToEditorHtml(value, sanitize);
207
+ if (outputFormat === "markdown") return chunkR3EJNGJV_cjs.markdownToEditorHtml(value, sanitize);
208
208
  return { html: sanitize(marked.marked.parse(value, { async: false }).trim()), source: null };
209
209
  }
210
210
  function EditorRoot({
@@ -264,12 +264,12 @@ function EditorRoot({
264
264
  const initialHtml = seed.html;
265
265
  const seedSource = seed.source;
266
266
  const extensions = react.useMemo(
267
- () => chunkKGJ2ORY6_cjs.mergeExtensions(instanceExtensions),
267
+ () => chunkR3EJNGJV_cjs.mergeExtensions(instanceExtensions),
268
268
  [instanceExtensions]
269
269
  );
270
270
  const getOutputValue = react.useCallback(
271
271
  (html) => {
272
- return outputFormat === "markdown" ? chunkKGJ2ORY6_cjs.htmlToMarkdown(html, seedSource) : html;
272
+ return outputFormat === "markdown" ? chunkR3EJNGJV_cjs.htmlToMarkdown(html, seedSource) : html;
273
273
  },
274
274
  [outputFormat, seedSource]
275
275
  );
@@ -353,7 +353,7 @@ function EditorRoot({
353
353
  fs.fullScreen && "overflow-auto"
354
354
  ),
355
355
  children: /* @__PURE__ */ jsxRuntime.jsx(
356
- chunkKGJ2ORY6_cjs.ContentRenderer,
356
+ chunkR3EJNGJV_cjs.ContentRenderer,
357
357
  {
358
358
  value,
359
359
  format: valueFormat !== "auto" ? valueFormat : outputFormat,
@@ -395,5 +395,5 @@ var Editor = Object.assign(EditorRoot, {
395
395
 
396
396
  exports.Editor = Editor;
397
397
  exports.useEditor = useEditor;
398
- //# sourceMappingURL=chunk-O4KZYGGC.cjs.map
399
- //# sourceMappingURL=chunk-O4KZYGGC.cjs.map
398
+ //# sourceMappingURL=chunk-5YRSYS2F.cjs.map
399
+ //# sourceMappingURL=chunk-5YRSYS2F.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/Editor/Editor.context.ts","../src/components/Editor/EditorSourceToggle.tsx","../src/components/Editor/EditorFullScreenToggle.tsx","../src/components/Editor/EditorToolbar.tsx","../src/components/Editor/EditorToolbarSeparator.tsx","../src/components/Editor/EditorContent.tsx","../src/components/Editor/Editor.tsx"],"names":["createContext","useContext","jsx","cn","FullScreenToggle","jsxs","Fragment","useRef","useEffect","useMemo","extensionEditorClasses","CodeView","proseClasses","sanitizeHtml","detectFormat","markdownToEditorHtml","marked","useControllableState","useFullScreen","useFieldMode","useState","mergeExtensions","useCallback","htmlToMarkdown","FullScreenProvider","ContentRenderer"],"mappings":"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","file":"chunk-O4KZYGGC.cjs","sourcesContent":["import { createContext, useContext } from \"react\";\nimport type { RefObject } from \"react\";\nimport type { RenderExtension } from \"../ContentRenderer/extensions\";\n\nexport interface EditorContextValue {\n contentRef: RefObject<HTMLDivElement | null>;\n exec: (command: string, arg?: string) => void;\n insertText: (text: string) => void;\n wrapSelection: (before: string, after: string) => void;\n outputFormat: \"html\" | \"markdown\";\n lineSpacing: number;\n placeholder?: string;\n /** Merged render extensions (global + instance). */\n extensions: RenderExtension[];\n /** Whether the raw-source view (textarea) is showing instead of the rich-text surface. */\n showSource: boolean;\n /** Toggle/set the raw-source view. */\n setShowSource: (showSource: boolean) => void;\n /** Whether the editor currently covers the viewport. */\n fullScreen: boolean;\n /** Enter/leave full screen. Goes through `onFullScreenChange` when controlled. */\n setFullScreen: (fullScreen: boolean) => void;\n /** Initial HTML content to load into the editor on mount */\n _initialHtml: string;\n /** @internal Called by EditorContent on input events */\n _onInput: () => void;\n /** @internal Raw source value (`value` in `outputFormat`), for the source textarea. */\n _sourceValue: string;\n /** @internal Commit an edit made directly in the source textarea. */\n _onSourceInput: (value: string) => void;\n}\n\nexport const EditorContext = createContext<EditorContextValue | null>(null);\n\nexport function useEditor(): EditorContextValue {\n const ctx = useContext(EditorContext);\n if (!ctx) {\n throw new Error(\"useEditor must be used within an <Editor> component\");\n }\n return ctx;\n}\n","import { cn } from \"../../utils/cn\";\nimport { useEditor } from \"./Editor.context\";\nimport type { EditorSourceToggleProps } from \"./Editor.types\";\n\n/**\n * Toolbar button that reveals the raw HTML/Markdown behind the editor. Reads\n * `showSource` / `setShowSource` from context, so it works in the default\n * toolbar and in any custom toolbar composed with `useEditor()`.\n */\nexport function EditorSourceToggle({\n className,\n icon = \"</>\",\n title = \"Source\",\n activeTitle = \"Rich text\",\n}: EditorSourceToggleProps) {\n const { showSource, setShowSource } = useEditor();\n\n return (\n <button\n type=\"button\"\n onClick={() => setShowSource(!showSource)}\n title={showSource ? activeTitle : title}\n aria-pressed={showSource}\n data-react-fancy-editor-source-toggle=\"\"\n className={cn(\n \"inline-flex h-8 items-center justify-center rounded-md px-2 font-mono text-xs transition-colors\",\n showSource\n ? \"bg-[color:var(--fancy-border,var(--color-zinc-200))] dark:bg-[color:var(--fancy-border-dark,var(--color-zinc-700))]\"\n : \"hover:bg-[color:var(--fancy-surface-muted,var(--color-zinc-100))] dark:hover:bg-[color:var(--fancy-surface-muted-dark,var(--color-zinc-800))]\",\n className,\n )}\n >\n {icon}\n </button>\n );\n}\n\nEditorSourceToggle.displayName = \"EditorSourceToggle\";\n","import { cn } from \"../../utils/cn\";\nimport { FullScreenToggle } from \"../FullScreen/FullScreenToggle\";\nimport type { EditorFullScreenToggleProps } from \"./Editor.types\";\n\n/**\n * Toolbar button that takes the editor full screen and back. The shared\n * `FullScreen.Toggle`, styled for the editor toolbar and carrying the editor's\n * own handle (`data-react-fancy-editor-fullscreen-toggle`) next to the shared\n * one (`data-react-fancy-fullscreen-toggle`).\n */\nexport function EditorFullScreenToggle({ className, enterIcon, exitIcon }: EditorFullScreenToggleProps) {\n return (\n <FullScreenToggle\n data-react-fancy-editor-fullscreen-toggle=\"\"\n enterIcon={enterIcon}\n exitIcon={exitIcon}\n className={cn(className)}\n />\n );\n}\n\nEditorFullScreenToggle.displayName = \"EditorFullScreenToggle\";\n","import { cn } from \"../../utils/cn\";\nimport { useEditor } from \"./Editor.context\";\nimport { EditorSourceToggle } from \"./EditorSourceToggle\";\nimport { EditorFullScreenToggle } from \"./EditorFullScreenToggle\";\nimport type { EditorToolbarProps } from \"./Editor.types\";\n\nconst DEFAULT_ACTIONS = [\n { icon: \"B\", label: \"Bold\", command: \"bold\" },\n { icon: \"I\", label: \"Italic\", command: \"italic\" },\n { icon: \"U\", label: \"Underline\", command: \"underline\" },\n { icon: \"S\", label: \"Strikethrough\", command: \"strikeThrough\" },\n];\n\nexport function EditorToolbar({\n actions = DEFAULT_ACTIONS,\n onAction,\n children,\n className,\n showSourceToggle = true,\n showFullScreenToggle = false,\n toolbarExtra,\n}: EditorToolbarProps) {\n const { exec, showSource } = useEditor();\n // `null` / `false` / `undefined` render nothing, so they must not add a\n // wrapper either: an unused slot leaves the toolbar byte-identical.\n const hasExtra = toolbarExtra !== undefined && toolbarExtra !== null && toolbarExtra !== false;\n\n return (\n <div\n data-react-fancy-editor-toolbar=\"\"\n className={cn(\n \"flex shrink-0 items-center gap-0.5 border-b border-[color:var(--fancy-border,var(--color-zinc-200))] px-2 py-1.5 dark:border-[color:var(--fancy-border-dark,var(--color-zinc-700))]\",\n className,\n )}\n >\n {children ?? (\n <>\n {actions.map((action) => (\n <button\n key={`${action.command}-${action.commandArg ?? \"\"}`}\n type=\"button\"\n // Rich-text commands don't apply to the raw-source textarea.\n disabled={showSource}\n onClick={() => {\n if (onAction) {\n onAction(action.command);\n } else {\n exec(action.command, action.commandArg);\n }\n }}\n title={action.label}\n className={cn(\n \"inline-flex h-8 w-8 items-center justify-center rounded-md text-sm transition-colors\",\n action.active\n ? \"bg-[color:var(--fancy-border,var(--color-zinc-200))] dark:bg-[color:var(--fancy-border-dark,var(--color-zinc-700))]\"\n : \"hover:bg-[color:var(--fancy-surface-muted,var(--color-zinc-100))] dark:hover:bg-[color:var(--fancy-surface-muted-dark,var(--color-zinc-800))]\",\n showSource && \"cursor-not-allowed opacity-40 hover:bg-transparent\",\n )}\n >\n {action.icon}\n </button>\n ))}\n {showSourceToggle && <EditorSourceToggle className=\"ml-auto\" />}\n {hasExtra && (\n <div\n data-react-fancy-editor-toolbar-extra=\"\"\n className={cn(\"flex items-center gap-0.5\", !showSourceToggle && \"ml-auto\")}\n >\n {toolbarExtra}\n </div>\n )}\n {showFullScreenToggle && (\n <EditorFullScreenToggle className={showSourceToggle || hasExtra ? undefined : \"ml-auto\"} />\n )}\n </>\n )}\n </div>\n );\n}\n\nEditorToolbar.displayName = \"EditorToolbar\";\n","export function EditorToolbarSeparator() {\n return (\n <span\n data-react-fancy-editor-toolbar-separator=\"\"\n className=\"mx-1 h-5 w-px bg-[color:var(--fancy-border,var(--color-zinc-200))] dark:bg-[color:var(--fancy-border-dark,var(--color-zinc-700))]\"\n />\n );\n}\n\nEditorToolbarSeparator.displayName = \"EditorToolbarSeparator\";\n","import { useEffect, useMemo, useRef } from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { CodeView } from \"../CodeView\";\nimport { useEditor } from \"./Editor.context\";\nimport { proseClasses, extensionEditorClasses } from \"./editor.utils\";\nimport type { EditorContentProps } from \"./Editor.types\";\n\nexport function EditorContent({ className, maxHeight: maxHeightProp, sourceClassName }: EditorContentProps) {\n const {\n contentRef,\n lineSpacing,\n placeholder,\n extensions,\n outputFormat,\n showSource,\n _initialHtml,\n _onInput,\n _sourceValue,\n _onSourceInput,\n fullScreen,\n } = useEditor();\n // Full screen means \"fill the viewport\": a height cap would leave the bottom\n // of the screen empty under a scrolled box.\n const maxHeight = fullScreen ? undefined : maxHeightProp;\n // Tracks which seed HTML is currently in the contentEditable. Seeding on the\n // seed VALUE (not a one-shot boolean) re-seeds when the source view rewrites\n // `value`, while still never re-seeding on plain keystrokes — typing leaves\n // `_initialHtml` untouched, so `seededHtml.current === _initialHtml` holds.\n const seededHtml = useRef<string | null>(null);\n\n useEffect(() => {\n // Source view replaces the contentEditable in the tree, so it unmounts.\n // Forget what we seeded — the div that returns is a fresh, empty one and\n // must always be re-seeded, even if `value` was left untouched.\n if (showSource) {\n seededHtml.current = null;\n return;\n }\n const el = contentRef.current;\n if (el && seededHtml.current !== _initialHtml) {\n el.innerHTML = _initialHtml;\n seededHtml.current = _initialHtml;\n }\n }, [contentRef, _initialHtml, showSource]);\n\n const extClasses = useMemo(\n () => extensionEditorClasses(extensions),\n [extensions],\n );\n\n if (showSource) {\n // Raw-source view — a syntax-highlighted code surface (HTML highlighted;\n // markdown/plain un-highlighted), built on the shared fancy-file-commons\n // primitives. It's a DIRECT child of the flex-column editor root (no\n // wrapper — a nested flex box collapses the fill), so `flex-auto` makes it\n // fill the editor body when height-constrained and grow with content\n // (≥ minHeight) when not. `maxHeight` caps + scrolls.\n return (\n <CodeView\n value={_sourceValue}\n onChange={_onSourceInput}\n language={outputFormat === \"html\" ? \"html\" : \"plaintext\"}\n placeholder={placeholder}\n maxHeight={maxHeight}\n className={cn(\"min-h-0 flex-auto\", sourceClassName)}\n />\n );\n }\n\n return (\n <div\n ref={contentRef}\n contentEditable\n suppressContentEditableWarning\n data-react-fancy-editor-content=\"\"\n data-placeholder={placeholder}\n onInput={_onInput}\n style={{\n lineHeight: lineSpacing,\n maxHeight: maxHeight ? `${maxHeight}px` : undefined,\n }}\n className={cn(\n \"min-h-[120px] flex-auto overflow-y-auto px-4 py-3 text-sm outline-none\",\n \"focus:outline-none\",\n proseClasses,\n extClasses,\n \"empty:before:content-[attr(data-placeholder)] empty:before:text-zinc-400 empty:before:pointer-events-none\",\n className,\n )}\n />\n );\n}\n\nEditorContent.displayName = \"EditorContent\";\n","import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { marked } from \"marked\";\nimport { cn } from \"../../utils/cn\";\nimport { sanitizeHtml } from \"../../utils/sanitize\";\nimport { useControllableState } from \"../../hooks\";\nimport { useFullScreen } from \"../../hooks/use-full-screen\";\nimport { FullScreenProvider } from \"../FullScreen/FullScreen.context\";\nimport { EditorContext } from \"./Editor.context\";\nimport { EditorToolbar } from \"./EditorToolbar\";\nimport { EditorToolbarSeparator } from \"./EditorToolbarSeparator\";\nimport { EditorSourceToggle } from \"./EditorSourceToggle\";\nimport { EditorContent } from \"./EditorContent\";\nimport { EditorFullScreenToggle } from \"./EditorFullScreenToggle\";\nimport { htmlToMarkdown, detectFormat, markdownToEditorHtml, type MarkdownSource } from \"./editor.utils\";\nimport { mergeExtensions } from \"../ContentRenderer/extensions\";\nimport { ContentRenderer } from \"../ContentRenderer/ContentRenderer\";\nimport { useFieldMode } from \"../inputs/mode/FieldMode.context\";\nimport type { EditorProps } from \"./Editor.types\";\n\ninterface Seed {\n html: string;\n /** Source map for source-preserving markdown output; null when there is none. */\n source: MarkdownSource | null;\n}\n\nfunction toHtml(\n value: string,\n outputFormat: \"html\" | \"markdown\",\n unsafe: boolean,\n valueFormat: \"markdown\" | \"html\" | \"auto\" = \"auto\",\n): Seed {\n if (!value) return { html: \"\", source: null };\n const sanitize = (html: string) => (unsafe ? html : sanitizeHtml(html));\n // An explicit valueFormat is authoritative — the sniff misclassifies\n // markdown that merely MENTIONS HTML-ish snippets (`<code>`, `<table`),\n // collapsing it into an innerHTML wall of text (#10).\n const format =\n valueFormat !== \"auto\"\n ? valueFormat\n : outputFormat === \"html\"\n ? \"html\"\n : detectFormat(value);\n if (format === \"html\") return { html: sanitize(value), source: null };\n // Markdown in, markdown out: tag each block with its source so untouched\n // blocks are emitted byte-identical.\n if (outputFormat === \"markdown\") return markdownToEditorHtml(value, sanitize);\n return { html: sanitize((marked.parse(value, { async: false }) as string).trim()), source: null };\n}\n\nfunction EditorRoot({\n children,\n className,\n value: controlledValue,\n defaultValue = \"\",\n onChange,\n outputFormat = \"html\",\n valueFormat = \"auto\",\n lineSpacing = 1.6,\n placeholder,\n mode: modeProp,\n extensions: instanceExtensions,\n unsafe = false,\n showSource: showSourceProp,\n defaultShowSource = false,\n onShowSourceChange,\n fullScreen: fullScreenProp,\n defaultFullScreen = false,\n onFullScreenChange,\n fullScreenMode = \"overlay\",\n copyButtons,\n clipboardWriter,\n onCopy,\n}: EditorProps) {\n const contentRef = useRef<HTMLDivElement | null>(null);\n const [value, setValue] = useControllableState(controlledValue, defaultValue, onChange);\n const [showSource, setShowSource] = useControllableState(\n showSourceProp,\n defaultShowSource,\n onShowSourceChange,\n );\n // Full screen is the element itself going `position: fixed`, not a portal:\n // reparenting would remount the contentEditable and lose the caret, the\n // browser's undo stack and the seeded HTML.\n const fs = useFullScreen<HTMLDivElement>({\n fullScreen: fullScreenProp,\n defaultFullScreen,\n onFullScreenChange,\n mode: fullScreenMode,\n });\n // View/edit mode — same resolution as the inputs: prop → <Form> context → \"edit\".\n const mode = useFieldMode(modeProp);\n const isView = mode === \"view\";\n\n // The value this editor last emitted through `onChange`. An incoming `value`\n // equal to it is our own keystroke echoing back; anything else came from\n // OUTSIDE — an async load, a host reset, a form repopulating.\n const lastEmitted = useRef<string | null>(null);\n\n // Bumped only on an external `value` change, so the seed memo below recomputes\n // for those and stays put while the user types. Without this, `value` was\n // excluded from the deps to avoid re-seeding on keystrokes, which also meant a\n // value arriving after mount was silently dropped and the editor stayed blank\n // forever (#15).\n const [externalSeed, setExternalSeed] = useState(0);\n useEffect(() => {\n if (value !== lastEmitted.current) setExternalSeed((n) => n + 1);\n }, [value]);\n\n const seed = useMemo(\n () => toHtml(value, outputFormat, unsafe, valueFormat),\n // Seed the contentEditable from the LIVE value when (re)entering edit mode —\n // and when returning from the raw-source view, which may have rewritten the\n // value out from under the rich-text surface. `value` itself stays out of\n // the deps so typing never re-seeds (which would fight the caret);\n // `externalSeed` covers the externally-driven case instead.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [isView, outputFormat, unsafe, valueFormat, showSource, externalSeed],\n );\n const initialHtml = seed.html;\n const seedSource = seed.source;\n\n const extensions = useMemo(\n () => mergeExtensions(instanceExtensions),\n [instanceExtensions],\n );\n\n const getOutputValue = useCallback(\n (html: string): string => {\n return outputFormat === \"markdown\" ? htmlToMarkdown(html, seedSource) : html;\n },\n [outputFormat, seedSource],\n );\n\n const handleInput = useCallback(() => {\n const el = contentRef.current;\n if (!el) return;\n const next = getOutputValue(el.innerHTML);\n // Record what we emitted BEFORE publishing it, so the value coming back in\n // is recognised as our own and does not trigger a re-seed mid-keystroke.\n lastEmitted.current = next;\n setValue(next);\n }, [setValue, getOutputValue]);\n\n const exec = useCallback(\n (command: string, arg?: string) => {\n const el = contentRef.current;\n if (!el) return;\n el.focus();\n document.execCommand(command, false, arg);\n handleInput();\n },\n [handleInput],\n );\n\n const insertText = useCallback(\n (text: string) => {\n const el = contentRef.current;\n if (!el) return;\n el.focus();\n document.execCommand(\"insertText\", false, text);\n handleInput();\n },\n [handleInput],\n );\n\n // The source textarea edits `value` directly — it is already the canonical\n // source in `outputFormat` (html or markdown), so no conversion round-trip.\n const handleSourceInput = useCallback(\n (next: string) => {\n // Also an internal emission — record it so typing in the source view is\n // not mistaken for an external change on every keystroke.\n lastEmitted.current = next;\n setValue(next);\n },\n [setValue],\n );\n\n const wrapSelection = useCallback(\n (before: string, after: string) => {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return;\n const range = sel.getRangeAt(0);\n const selectedText = range.toString();\n const el = contentRef.current;\n if (!el) return;\n el.focus();\n document.execCommand(\"insertText\", false, `${before}${selectedText}${after}`);\n handleInput();\n },\n [handleInput],\n );\n\n const contextValue = {\n contentRef,\n exec,\n insertText,\n wrapSelection,\n outputFormat,\n lineSpacing,\n placeholder,\n extensions,\n showSource,\n setShowSource,\n fullScreen: fs.fullScreen,\n setFullScreen: fs.setFullScreen,\n _initialHtml: initialHtml,\n _onInput: handleInput,\n _sourceValue: value,\n _onSourceInput: handleSourceInput,\n };\n\n // View mode — render the value read-only through ContentRenderer, matching the\n // editor's own format (markdown/html), instead of the editable toolbar+content\n // tree. Driven by `mode` / a `<Form mode=\"view\">`, exactly like the inputs.\n if (isView) {\n return (\n <FullScreenProvider value={fs}>\n <div\n {...fs.targetProps}\n data-react-fancy-editor=\"\"\n data-mode=\"view\"\n className={cn(\n \"overflow-hidden rounded-xl border border-[color:var(--fancy-border,var(--color-zinc-200))] bg-[color:var(--fancy-surface,var(--color-white))] dark:border-[color:var(--fancy-border-dark,var(--color-zinc-700))] dark:bg-[color:var(--fancy-surface-dark,var(--color-zinc-900))]\",\n className,\n // Read-only content taller than the viewport must scroll in place.\n fs.fullScreen && \"overflow-auto\",\n )}\n >\n <ContentRenderer\n value={value}\n format={valueFormat !== \"auto\" ? valueFormat : outputFormat}\n lineSpacing={lineSpacing}\n extensions={instanceExtensions}\n unsafe={unsafe}\n copyButtons={copyButtons}\n clipboardWriter={clipboardWriter}\n onCopy={onCopy}\n className=\"px-4 py-3\"\n />\n </div>\n </FullScreenProvider>\n );\n }\n\n return (\n <EditorContext.Provider value={contextValue}>\n <FullScreenProvider value={fs}>\n <div\n {...fs.targetProps}\n data-react-fancy-editor=\"\"\n data-mode=\"edit\"\n className={cn(\n \"flex flex-col overflow-hidden rounded-xl border border-[color:var(--fancy-border,var(--color-zinc-200))] bg-[color:var(--fancy-surface,var(--color-white))] dark:border-[color:var(--fancy-border-dark,var(--color-zinc-700))] dark:bg-[color:var(--fancy-surface-dark,var(--color-zinc-900))]\",\n className,\n )}\n >\n {children}\n </div>\n </FullScreenProvider>\n </EditorContext.Provider>\n );\n}\n\nconst ToolbarWithSeparator = Object.assign(EditorToolbar, {\n Separator: EditorToolbarSeparator,\n});\n\nexport const Editor = Object.assign(EditorRoot, {\n Toolbar: ToolbarWithSeparator,\n Content: EditorContent,\n SourceToggle: EditorSourceToggle,\n FullScreenToggle: EditorFullScreenToggle,\n});\n"]}
1
+ {"version":3,"sources":["../src/components/Editor/Editor.context.ts","../src/components/Editor/EditorSourceToggle.tsx","../src/components/Editor/EditorFullScreenToggle.tsx","../src/components/Editor/EditorToolbar.tsx","../src/components/Editor/EditorToolbarSeparator.tsx","../src/components/Editor/EditorContent.tsx","../src/components/Editor/Editor.tsx"],"names":["createContext","useContext","jsx","cn","FullScreenToggle","jsxs","Fragment","useRef","useEffect","useMemo","extensionEditorClasses","CodeView","proseClasses","sanitizeHtml","detectFormat","markdownToEditorHtml","marked","useControllableState","useFullScreen","useFieldMode","useState","mergeExtensions","useCallback","htmlToMarkdown","FullScreenProvider","ContentRenderer"],"mappings":"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","file":"chunk-5YRSYS2F.cjs","sourcesContent":["import { createContext, useContext } from \"react\";\nimport type { RefObject } from \"react\";\nimport type { RenderExtension } from \"../ContentRenderer/extensions\";\n\nexport interface EditorContextValue {\n contentRef: RefObject<HTMLDivElement | null>;\n exec: (command: string, arg?: string) => void;\n insertText: (text: string) => void;\n wrapSelection: (before: string, after: string) => void;\n outputFormat: \"html\" | \"markdown\";\n lineSpacing: number;\n placeholder?: string;\n /** Merged render extensions (global + instance). */\n extensions: RenderExtension[];\n /** Whether the raw-source view (textarea) is showing instead of the rich-text surface. */\n showSource: boolean;\n /** Toggle/set the raw-source view. */\n setShowSource: (showSource: boolean) => void;\n /** Whether the editor currently covers the viewport. */\n fullScreen: boolean;\n /** Enter/leave full screen. Goes through `onFullScreenChange` when controlled. */\n setFullScreen: (fullScreen: boolean) => void;\n /** Initial HTML content to load into the editor on mount */\n _initialHtml: string;\n /** @internal Called by EditorContent on input events */\n _onInput: () => void;\n /** @internal Raw source value (`value` in `outputFormat`), for the source textarea. */\n _sourceValue: string;\n /** @internal Commit an edit made directly in the source textarea. */\n _onSourceInput: (value: string) => void;\n}\n\nexport const EditorContext = createContext<EditorContextValue | null>(null);\n\nexport function useEditor(): EditorContextValue {\n const ctx = useContext(EditorContext);\n if (!ctx) {\n throw new Error(\"useEditor must be used within an <Editor> component\");\n }\n return ctx;\n}\n","import { cn } from \"../../utils/cn\";\nimport { useEditor } from \"./Editor.context\";\nimport type { EditorSourceToggleProps } from \"./Editor.types\";\n\n/**\n * Toolbar button that reveals the raw HTML/Markdown behind the editor. Reads\n * `showSource` / `setShowSource` from context, so it works in the default\n * toolbar and in any custom toolbar composed with `useEditor()`.\n */\nexport function EditorSourceToggle({\n className,\n icon = \"</>\",\n title = \"Source\",\n activeTitle = \"Rich text\",\n}: EditorSourceToggleProps) {\n const { showSource, setShowSource } = useEditor();\n\n return (\n <button\n type=\"button\"\n onClick={() => setShowSource(!showSource)}\n title={showSource ? activeTitle : title}\n aria-pressed={showSource}\n data-react-fancy-editor-source-toggle=\"\"\n className={cn(\n \"inline-flex h-8 items-center justify-center rounded-md px-2 font-mono text-xs transition-colors\",\n showSource\n ? \"bg-[color:var(--fancy-border,var(--color-zinc-200))] dark:bg-[color:var(--fancy-border-dark,var(--color-zinc-700))]\"\n : \"hover:bg-[color:var(--fancy-surface-muted,var(--color-zinc-100))] dark:hover:bg-[color:var(--fancy-surface-muted-dark,var(--color-zinc-800))]\",\n className,\n )}\n >\n {icon}\n </button>\n );\n}\n\nEditorSourceToggle.displayName = \"EditorSourceToggle\";\n","import { cn } from \"../../utils/cn\";\nimport { FullScreenToggle } from \"../FullScreen/FullScreenToggle\";\nimport type { EditorFullScreenToggleProps } from \"./Editor.types\";\n\n/**\n * Toolbar button that takes the editor full screen and back. The shared\n * `FullScreen.Toggle`, styled for the editor toolbar and carrying the editor's\n * own handle (`data-react-fancy-editor-fullscreen-toggle`) next to the shared\n * one (`data-react-fancy-fullscreen-toggle`).\n */\nexport function EditorFullScreenToggle({ className, enterIcon, exitIcon }: EditorFullScreenToggleProps) {\n return (\n <FullScreenToggle\n data-react-fancy-editor-fullscreen-toggle=\"\"\n enterIcon={enterIcon}\n exitIcon={exitIcon}\n className={cn(className)}\n />\n );\n}\n\nEditorFullScreenToggle.displayName = \"EditorFullScreenToggle\";\n","import { cn } from \"../../utils/cn\";\nimport { useEditor } from \"./Editor.context\";\nimport { EditorSourceToggle } from \"./EditorSourceToggle\";\nimport { EditorFullScreenToggle } from \"./EditorFullScreenToggle\";\nimport type { EditorToolbarProps } from \"./Editor.types\";\n\nconst DEFAULT_ACTIONS = [\n { icon: \"B\", label: \"Bold\", command: \"bold\" },\n { icon: \"I\", label: \"Italic\", command: \"italic\" },\n { icon: \"U\", label: \"Underline\", command: \"underline\" },\n { icon: \"S\", label: \"Strikethrough\", command: \"strikeThrough\" },\n];\n\nexport function EditorToolbar({\n actions = DEFAULT_ACTIONS,\n onAction,\n children,\n className,\n showSourceToggle = true,\n showFullScreenToggle = false,\n toolbarExtra,\n}: EditorToolbarProps) {\n const { exec, showSource } = useEditor();\n // `null` / `false` / `undefined` render nothing, so they must not add a\n // wrapper either: an unused slot leaves the toolbar byte-identical.\n const hasExtra = toolbarExtra !== undefined && toolbarExtra !== null && toolbarExtra !== false;\n\n return (\n <div\n data-react-fancy-editor-toolbar=\"\"\n className={cn(\n \"flex shrink-0 items-center gap-0.5 border-b border-[color:var(--fancy-border,var(--color-zinc-200))] px-2 py-1.5 dark:border-[color:var(--fancy-border-dark,var(--color-zinc-700))]\",\n className,\n )}\n >\n {children ?? (\n <>\n {actions.map((action) => (\n <button\n key={`${action.command}-${action.commandArg ?? \"\"}`}\n type=\"button\"\n // Rich-text commands don't apply to the raw-source textarea.\n disabled={showSource}\n onClick={() => {\n if (onAction) {\n onAction(action.command);\n } else {\n exec(action.command, action.commandArg);\n }\n }}\n title={action.label}\n className={cn(\n \"inline-flex h-8 w-8 items-center justify-center rounded-md text-sm transition-colors\",\n action.active\n ? \"bg-[color:var(--fancy-border,var(--color-zinc-200))] dark:bg-[color:var(--fancy-border-dark,var(--color-zinc-700))]\"\n : \"hover:bg-[color:var(--fancy-surface-muted,var(--color-zinc-100))] dark:hover:bg-[color:var(--fancy-surface-muted-dark,var(--color-zinc-800))]\",\n showSource && \"cursor-not-allowed opacity-40 hover:bg-transparent\",\n )}\n >\n {action.icon}\n </button>\n ))}\n {showSourceToggle && <EditorSourceToggle className=\"ml-auto\" />}\n {hasExtra && (\n <div\n data-react-fancy-editor-toolbar-extra=\"\"\n className={cn(\"flex items-center gap-0.5\", !showSourceToggle && \"ml-auto\")}\n >\n {toolbarExtra}\n </div>\n )}\n {showFullScreenToggle && (\n <EditorFullScreenToggle className={showSourceToggle || hasExtra ? undefined : \"ml-auto\"} />\n )}\n </>\n )}\n </div>\n );\n}\n\nEditorToolbar.displayName = \"EditorToolbar\";\n","export function EditorToolbarSeparator() {\n return (\n <span\n data-react-fancy-editor-toolbar-separator=\"\"\n className=\"mx-1 h-5 w-px bg-[color:var(--fancy-border,var(--color-zinc-200))] dark:bg-[color:var(--fancy-border-dark,var(--color-zinc-700))]\"\n />\n );\n}\n\nEditorToolbarSeparator.displayName = \"EditorToolbarSeparator\";\n","import { useEffect, useMemo, useRef } from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { CodeView } from \"../CodeView\";\nimport { useEditor } from \"./Editor.context\";\nimport { proseClasses, extensionEditorClasses } from \"./editor.utils\";\nimport type { EditorContentProps } from \"./Editor.types\";\n\nexport function EditorContent({ className, maxHeight: maxHeightProp, sourceClassName }: EditorContentProps) {\n const {\n contentRef,\n lineSpacing,\n placeholder,\n extensions,\n outputFormat,\n showSource,\n _initialHtml,\n _onInput,\n _sourceValue,\n _onSourceInput,\n fullScreen,\n } = useEditor();\n // Full screen means \"fill the viewport\": a height cap would leave the bottom\n // of the screen empty under a scrolled box.\n const maxHeight = fullScreen ? undefined : maxHeightProp;\n // Tracks which seed HTML is currently in the contentEditable. Seeding on the\n // seed VALUE (not a one-shot boolean) re-seeds when the source view rewrites\n // `value`, while still never re-seeding on plain keystrokes — typing leaves\n // `_initialHtml` untouched, so `seededHtml.current === _initialHtml` holds.\n const seededHtml = useRef<string | null>(null);\n\n useEffect(() => {\n // Source view replaces the contentEditable in the tree, so it unmounts.\n // Forget what we seeded — the div that returns is a fresh, empty one and\n // must always be re-seeded, even if `value` was left untouched.\n if (showSource) {\n seededHtml.current = null;\n return;\n }\n const el = contentRef.current;\n if (el && seededHtml.current !== _initialHtml) {\n el.innerHTML = _initialHtml;\n seededHtml.current = _initialHtml;\n }\n }, [contentRef, _initialHtml, showSource]);\n\n const extClasses = useMemo(\n () => extensionEditorClasses(extensions),\n [extensions],\n );\n\n if (showSource) {\n // Raw-source view — a syntax-highlighted code surface (HTML highlighted;\n // markdown/plain un-highlighted), built on the shared fancy-file-commons\n // primitives. It's a DIRECT child of the flex-column editor root (no\n // wrapper — a nested flex box collapses the fill), so `flex-auto` makes it\n // fill the editor body when height-constrained and grow with content\n // (≥ minHeight) when not. `maxHeight` caps + scrolls.\n return (\n <CodeView\n value={_sourceValue}\n onChange={_onSourceInput}\n language={outputFormat === \"html\" ? \"html\" : \"plaintext\"}\n placeholder={placeholder}\n maxHeight={maxHeight}\n className={cn(\"min-h-0 flex-auto\", sourceClassName)}\n />\n );\n }\n\n return (\n <div\n ref={contentRef}\n contentEditable\n suppressContentEditableWarning\n data-react-fancy-editor-content=\"\"\n data-placeholder={placeholder}\n onInput={_onInput}\n style={{\n lineHeight: lineSpacing,\n maxHeight: maxHeight ? `${maxHeight}px` : undefined,\n }}\n className={cn(\n \"min-h-[120px] flex-auto overflow-y-auto px-4 py-3 text-sm outline-none\",\n \"focus:outline-none\",\n proseClasses,\n extClasses,\n \"empty:before:content-[attr(data-placeholder)] empty:before:text-zinc-400 empty:before:pointer-events-none\",\n className,\n )}\n />\n );\n}\n\nEditorContent.displayName = \"EditorContent\";\n","import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { marked } from \"marked\";\nimport { cn } from \"../../utils/cn\";\nimport { sanitizeHtml } from \"../../utils/sanitize\";\nimport { useControllableState } from \"../../hooks\";\nimport { useFullScreen } from \"../../hooks/use-full-screen\";\nimport { FullScreenProvider } from \"../FullScreen/FullScreen.context\";\nimport { EditorContext } from \"./Editor.context\";\nimport { EditorToolbar } from \"./EditorToolbar\";\nimport { EditorToolbarSeparator } from \"./EditorToolbarSeparator\";\nimport { EditorSourceToggle } from \"./EditorSourceToggle\";\nimport { EditorContent } from \"./EditorContent\";\nimport { EditorFullScreenToggle } from \"./EditorFullScreenToggle\";\nimport { htmlToMarkdown, detectFormat, markdownToEditorHtml, type MarkdownSource } from \"./editor.utils\";\nimport { mergeExtensions } from \"../ContentRenderer/extensions\";\nimport { ContentRenderer } from \"../ContentRenderer/ContentRenderer\";\nimport { useFieldMode } from \"../inputs/mode/FieldMode.context\";\nimport type { EditorProps } from \"./Editor.types\";\n\ninterface Seed {\n html: string;\n /** Source map for source-preserving markdown output; null when there is none. */\n source: MarkdownSource | null;\n}\n\nfunction toHtml(\n value: string,\n outputFormat: \"html\" | \"markdown\",\n unsafe: boolean,\n valueFormat: \"markdown\" | \"html\" | \"auto\" = \"auto\",\n): Seed {\n if (!value) return { html: \"\", source: null };\n const sanitize = (html: string) => (unsafe ? html : sanitizeHtml(html));\n // An explicit valueFormat is authoritative — the sniff misclassifies\n // markdown that merely MENTIONS HTML-ish snippets (`<code>`, `<table`),\n // collapsing it into an innerHTML wall of text (#10).\n const format =\n valueFormat !== \"auto\"\n ? valueFormat\n : outputFormat === \"html\"\n ? \"html\"\n : detectFormat(value);\n if (format === \"html\") return { html: sanitize(value), source: null };\n // Markdown in, markdown out: tag each block with its source so untouched\n // blocks are emitted byte-identical.\n if (outputFormat === \"markdown\") return markdownToEditorHtml(value, sanitize);\n return { html: sanitize((marked.parse(value, { async: false }) as string).trim()), source: null };\n}\n\nfunction EditorRoot({\n children,\n className,\n value: controlledValue,\n defaultValue = \"\",\n onChange,\n outputFormat = \"html\",\n valueFormat = \"auto\",\n lineSpacing = 1.6,\n placeholder,\n mode: modeProp,\n extensions: instanceExtensions,\n unsafe = false,\n showSource: showSourceProp,\n defaultShowSource = false,\n onShowSourceChange,\n fullScreen: fullScreenProp,\n defaultFullScreen = false,\n onFullScreenChange,\n fullScreenMode = \"overlay\",\n copyButtons,\n clipboardWriter,\n onCopy,\n}: EditorProps) {\n const contentRef = useRef<HTMLDivElement | null>(null);\n const [value, setValue] = useControllableState(controlledValue, defaultValue, onChange);\n const [showSource, setShowSource] = useControllableState(\n showSourceProp,\n defaultShowSource,\n onShowSourceChange,\n );\n // Full screen is the element itself going `position: fixed`, not a portal:\n // reparenting would remount the contentEditable and lose the caret, the\n // browser's undo stack and the seeded HTML.\n const fs = useFullScreen<HTMLDivElement>({\n fullScreen: fullScreenProp,\n defaultFullScreen,\n onFullScreenChange,\n mode: fullScreenMode,\n });\n // View/edit mode — same resolution as the inputs: prop → <Form> context → \"edit\".\n const mode = useFieldMode(modeProp);\n const isView = mode === \"view\";\n\n // The value this editor last emitted through `onChange`. An incoming `value`\n // equal to it is our own keystroke echoing back; anything else came from\n // OUTSIDE — an async load, a host reset, a form repopulating.\n const lastEmitted = useRef<string | null>(null);\n\n // Bumped only on an external `value` change, so the seed memo below recomputes\n // for those and stays put while the user types. Without this, `value` was\n // excluded from the deps to avoid re-seeding on keystrokes, which also meant a\n // value arriving after mount was silently dropped and the editor stayed blank\n // forever (#15).\n const [externalSeed, setExternalSeed] = useState(0);\n useEffect(() => {\n if (value !== lastEmitted.current) setExternalSeed((n) => n + 1);\n }, [value]);\n\n const seed = useMemo(\n () => toHtml(value, outputFormat, unsafe, valueFormat),\n // Seed the contentEditable from the LIVE value when (re)entering edit mode —\n // and when returning from the raw-source view, which may have rewritten the\n // value out from under the rich-text surface. `value` itself stays out of\n // the deps so typing never re-seeds (which would fight the caret);\n // `externalSeed` covers the externally-driven case instead.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [isView, outputFormat, unsafe, valueFormat, showSource, externalSeed],\n );\n const initialHtml = seed.html;\n const seedSource = seed.source;\n\n const extensions = useMemo(\n () => mergeExtensions(instanceExtensions),\n [instanceExtensions],\n );\n\n const getOutputValue = useCallback(\n (html: string): string => {\n return outputFormat === \"markdown\" ? htmlToMarkdown(html, seedSource) : html;\n },\n [outputFormat, seedSource],\n );\n\n const handleInput = useCallback(() => {\n const el = contentRef.current;\n if (!el) return;\n const next = getOutputValue(el.innerHTML);\n // Record what we emitted BEFORE publishing it, so the value coming back in\n // is recognised as our own and does not trigger a re-seed mid-keystroke.\n lastEmitted.current = next;\n setValue(next);\n }, [setValue, getOutputValue]);\n\n const exec = useCallback(\n (command: string, arg?: string) => {\n const el = contentRef.current;\n if (!el) return;\n el.focus();\n document.execCommand(command, false, arg);\n handleInput();\n },\n [handleInput],\n );\n\n const insertText = useCallback(\n (text: string) => {\n const el = contentRef.current;\n if (!el) return;\n el.focus();\n document.execCommand(\"insertText\", false, text);\n handleInput();\n },\n [handleInput],\n );\n\n // The source textarea edits `value` directly — it is already the canonical\n // source in `outputFormat` (html or markdown), so no conversion round-trip.\n const handleSourceInput = useCallback(\n (next: string) => {\n // Also an internal emission — record it so typing in the source view is\n // not mistaken for an external change on every keystroke.\n lastEmitted.current = next;\n setValue(next);\n },\n [setValue],\n );\n\n const wrapSelection = useCallback(\n (before: string, after: string) => {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return;\n const range = sel.getRangeAt(0);\n const selectedText = range.toString();\n const el = contentRef.current;\n if (!el) return;\n el.focus();\n document.execCommand(\"insertText\", false, `${before}${selectedText}${after}`);\n handleInput();\n },\n [handleInput],\n );\n\n const contextValue = {\n contentRef,\n exec,\n insertText,\n wrapSelection,\n outputFormat,\n lineSpacing,\n placeholder,\n extensions,\n showSource,\n setShowSource,\n fullScreen: fs.fullScreen,\n setFullScreen: fs.setFullScreen,\n _initialHtml: initialHtml,\n _onInput: handleInput,\n _sourceValue: value,\n _onSourceInput: handleSourceInput,\n };\n\n // View mode — render the value read-only through ContentRenderer, matching the\n // editor's own format (markdown/html), instead of the editable toolbar+content\n // tree. Driven by `mode` / a `<Form mode=\"view\">`, exactly like the inputs.\n if (isView) {\n return (\n <FullScreenProvider value={fs}>\n <div\n {...fs.targetProps}\n data-react-fancy-editor=\"\"\n data-mode=\"view\"\n className={cn(\n \"overflow-hidden rounded-xl border border-[color:var(--fancy-border,var(--color-zinc-200))] bg-[color:var(--fancy-surface,var(--color-white))] dark:border-[color:var(--fancy-border-dark,var(--color-zinc-700))] dark:bg-[color:var(--fancy-surface-dark,var(--color-zinc-900))]\",\n className,\n // Read-only content taller than the viewport must scroll in place.\n fs.fullScreen && \"overflow-auto\",\n )}\n >\n <ContentRenderer\n value={value}\n format={valueFormat !== \"auto\" ? valueFormat : outputFormat}\n lineSpacing={lineSpacing}\n extensions={instanceExtensions}\n unsafe={unsafe}\n copyButtons={copyButtons}\n clipboardWriter={clipboardWriter}\n onCopy={onCopy}\n className=\"px-4 py-3\"\n />\n </div>\n </FullScreenProvider>\n );\n }\n\n return (\n <EditorContext.Provider value={contextValue}>\n <FullScreenProvider value={fs}>\n <div\n {...fs.targetProps}\n data-react-fancy-editor=\"\"\n data-mode=\"edit\"\n className={cn(\n \"flex flex-col overflow-hidden rounded-xl border border-[color:var(--fancy-border,var(--color-zinc-200))] bg-[color:var(--fancy-surface,var(--color-white))] dark:border-[color:var(--fancy-border-dark,var(--color-zinc-700))] dark:bg-[color:var(--fancy-surface-dark,var(--color-zinc-900))]\",\n className,\n )}\n >\n {children}\n </div>\n </FullScreenProvider>\n </EditorContext.Provider>\n );\n}\n\nconst ToolbarWithSeparator = Object.assign(EditorToolbar, {\n Separator: EditorToolbarSeparator,\n});\n\nexport const Editor = Object.assign(EditorRoot, {\n Toolbar: ToolbarWithSeparator,\n Content: EditorContent,\n SourceToggle: EditorSourceToggle,\n FullScreenToggle: EditorFullScreenToggle,\n});\n"]}