@particle-academy/fancy-code 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @particle-academy/fancy-code
2
2
 
3
- Lightweight embedded code editor built on CodeMirror 6. Compound component API with custom toolbar buttons, syntax highlighting color schemes, and extensible language/theme registries.
3
+ Lightweight embedded code editor with syntax highlighting, custom toolbar buttons, and extensible language/theme registries. Part of the `@particle-academy` component ecosystem.
4
4
 
5
5
  ## Installation
6
6
 
@@ -17,8 +17,6 @@ yarn add @particle-academy/fancy-code
17
17
 
18
18
  **Peer dependencies:** `react >= 18`, `react-dom >= 18`, `@particle-academy/react-fancy >= 1.5`
19
19
 
20
- **Bundled dependencies:** CodeMirror 6 (state, view, commands, language, search, autocomplete), language packages (JavaScript, TypeScript, HTML, PHP), `@lezer/highlight`
21
-
22
20
  ## Usage
23
21
 
24
22
  Add the `@source` directive to your main CSS file so Tailwind v4 scans the component library:
@@ -66,7 +64,7 @@ pnpm --filter @particle-academy/fancy-code clean # Remove dist/
66
64
  | `CodeEditor` | Root wrapper — context provider, state management |
67
65
  | `CodeEditor.Toolbar` | Action bar with default buttons or custom children |
68
66
  | `CodeEditor.Toolbar.Separator` | Vertical divider between toolbar groups |
69
- | `CodeEditor.Panel` | CodeMirror editing surface |
67
+ | `CodeEditor.Panel` | Code editing surface |
70
68
  | `CodeEditor.StatusBar` | Cursor position, language, tab size display |
71
69
 
72
70
  ### CodeEditor Props
@@ -88,7 +86,7 @@ interface CodeEditorProps {
88
86
  placeholder?: string;
89
87
  minHeight?: number; // Minimum height in px
90
88
  maxHeight?: number; // Max height before scrolling
91
- extensions?: Extension[]; // Additional CodeMirror extensions
89
+ extensions?: Extension[]; // Additional editor extensions
92
90
  }
93
91
  ```
94
92
 
@@ -102,7 +100,7 @@ import { Action } from "@particle-academy/react-fancy";
102
100
 
103
101
  function RunButton() {
104
102
  const { getValue } = useCodeEditor();
105
- return <Action size="xs" onClick={() => eval(getValue())}>Run</Action>;
103
+ return <Action size="xs" onClick={() => run(getValue())}>Run</Action>;
106
104
  }
107
105
 
108
106
  <CodeEditor value={code} onChange={setCode} language="javascript">
@@ -118,7 +116,6 @@ function RunButton() {
118
116
 
119
117
  | Method / Property | Description |
120
118
  |-------------------|-------------|
121
- | `view` | The CodeMirror `EditorView` instance (null before mount) |
122
119
  | `getValue()` | Get current document text |
123
120
  | `getSelection()` | Get currently selected text |
124
121
  | `setValue(text)` | Replace entire document |
@@ -205,13 +202,15 @@ Add languages beyond the four built-ins using `registerLanguage`:
205
202
 
206
203
  ```tsx
207
204
  import { registerLanguage } from "@particle-academy/fancy-code";
208
- import { python } from "@codemirror/lang-python";
209
205
 
210
- // Synchronous (package already installed)
211
206
  registerLanguage({
212
207
  name: "Python",
213
208
  aliases: ["py", "python"],
214
- support: () => python(),
209
+ support: () => {
210
+ // Return a LanguageSupport instance
211
+ const { python } = require("@codemirror/lang-python");
212
+ return python();
213
+ },
215
214
  });
216
215
 
217
216
  // Lazy-loaded
@@ -245,27 +244,12 @@ Create custom syntax highlighting color schemes using `registerTheme`:
245
244
 
246
245
  ```tsx
247
246
  import { registerTheme } from "@particle-academy/fancy-code";
248
- import { EditorView } from "@codemirror/view";
249
- import { HighlightStyle } from "@codemirror/language";
250
- import { tags } from "@lezer/highlight";
251
247
 
252
248
  registerTheme({
253
249
  name: "monokai",
254
250
  variant: "dark",
255
- editorTheme: EditorView.theme({
256
- "&": { backgroundColor: "#272822", color: "#f8f8f2" },
257
- ".cm-gutters": { backgroundColor: "#272822", color: "#75715e" },
258
- ".cm-activeLine": { backgroundColor: "#3e3d32" },
259
- // ... other editor chrome styles
260
- }, { dark: true }),
261
- highlightStyle: HighlightStyle.define([
262
- { tag: tags.keyword, color: "#f92672" },
263
- { tag: tags.string, color: "#e6db74" },
264
- { tag: tags.function(tags.variableName), color: "#a6e22e" },
265
- { tag: tags.number, color: "#ae81ff" },
266
- { tag: tags.comment, color: "#75715e", fontStyle: "italic" },
267
- // ... other token styles
268
- ]),
251
+ editorTheme: /* editor chrome styles (background, gutter, cursor, selection) */,
252
+ highlightStyle: /* token color definitions (keywords, strings, comments, etc.) */,
269
253
  });
270
254
  ```
271
255
 
@@ -280,16 +264,14 @@ Then use it:
280
264
  ```ts
281
265
  interface ThemeDefinition {
282
266
  name: string; // Unique theme name
283
- variant: "light" | "dark"; // For EditorView.darkTheme
284
- editorTheme: Extension; // EditorView.theme({...}) gutter, cursor, selection
285
- highlightStyle: HighlightStyle; // HighlightStyle.define([...]) token colors
267
+ variant: "light" | "dark"; // Light or dark base
268
+ editorTheme: Extension; // Editor chrome styles (gutter, cursor, selection)
269
+ highlightStyle: HighlightStyle; // Syntax token color definitions
286
270
  }
287
271
  ```
288
272
 
289
273
  ## Built-in Features
290
274
 
291
- The editor includes these CodeMirror extensions out of the box:
292
-
293
275
  - Syntax highlighting with language-aware tokenization
294
276
  - Line numbers with active line gutter highlight
295
277
  - Active line highlighting
@@ -302,7 +284,19 @@ The editor includes these CodeMirror extensions out of the box:
302
284
  - Selection highlighting
303
285
  - Tab key indentation
304
286
 
305
- All features are reconfigurable at runtime via compartments — switching languages, themes, line numbers, word wrap, tab size, and read-only mode happens without recreating the editor.
287
+ All features are reconfigurable at runtime — switching languages, themes, line numbers, word wrap, tab size, and read-only mode happens without recreating the editor.
288
+
289
+ ## Customization
290
+
291
+ All components render `data-fancy-code-*` attributes on their root elements for external CSS targeting:
292
+
293
+ | Attribute | Element |
294
+ |-----------|---------|
295
+ | `data-fancy-code-editor` | Root wrapper |
296
+ | `data-fancy-code-toolbar` | Toolbar bar |
297
+ | `data-fancy-code-toolbar-separator` | Toolbar separator |
298
+ | `data-fancy-code-panel` | Editing surface |
299
+ | `data-fancy-code-statusbar` | Status bar |
306
300
 
307
301
  ## Architecture
308
302
 
@@ -312,42 +306,32 @@ All features are reconfigurable at runtime via compartments — switching langua
312
306
  src/
313
307
  ├── components/
314
308
  │ └── CodeEditor/
315
- │ ├── CodeEditor.tsx # Root compound component + context
316
- │ ├── CodeEditor.types.ts # All prop/context types
317
- │ ├── CodeEditor.context.ts # React context + useCodeEditor hook
318
- │ ├── CodeEditorPanel.tsx # CodeMirror mount point
319
- │ ├── CodeEditorToolbar.tsx # Default toolbar + custom children
309
+ │ ├── CodeEditor.tsx # Root compound component + context
310
+ │ ├── CodeEditor.types.ts # All prop/context types
311
+ │ ├── CodeEditor.context.ts # React context + useCodeEditor hook
312
+ │ ├── CodeEditorPanel.tsx # Editing surface
313
+ │ ├── CodeEditorToolbar.tsx # Default toolbar + custom children
320
314
  │ ├── CodeEditorToolbarSeparator.tsx
321
- │ ├── CodeEditorStatusBar.tsx # Cursor/language/tab display
315
+ │ ├── CodeEditorStatusBar.tsx # Cursor/language/tab display
322
316
  │ └── index.ts
323
317
  ├── hooks/
324
- │ ├── use-codemirror.ts # Core CM lifecycle + compartments
325
- │ └── use-dark-mode.ts # Reactive prefers-color-scheme
318
+ │ ├── use-codemirror.ts # Core editor lifecycle
319
+ │ └── use-dark-mode.ts # Reactive prefers-color-scheme
326
320
  ├── languages/
327
- │ ├── registry.ts # Global language registry
328
- │ ├── builtin.ts # JS, TS, HTML, PHP registrations
329
- │ ├── types.ts # LanguageDefinition type
321
+ │ ├── registry.ts # Global language registry
322
+ │ ├── builtin.ts # JS, TS, HTML, PHP registrations
323
+ │ ├── types.ts # LanguageDefinition type
330
324
  │ └── index.ts
331
325
  ├── themes/
332
- │ ├── registry.ts # Global theme registry
333
- │ ├── light.ts # Built-in light color scheme
334
- │ ├── dark.ts # Built-in dark color scheme
335
- │ ├── types.ts # ThemeDefinition type
326
+ │ ├── registry.ts # Global theme registry
327
+ │ ├── light.ts # Built-in light color scheme
328
+ │ ├── dark.ts # Built-in dark color scheme
329
+ │ ├── types.ts # ThemeDefinition type
336
330
  │ └── index.ts
337
- ├── styles.css # Base CodeMirror structural styles
338
- └── index.ts # Public API
331
+ ├── styles.css # Base structural styles
332
+ └── index.ts # Public API
339
333
  ```
340
334
 
341
- ### Data Attributes
342
-
343
- | Attribute | Element |
344
- |-----------|---------|
345
- | `data-fancy-code-editor` | Root wrapper |
346
- | `data-fancy-code-toolbar` | Toolbar bar |
347
- | `data-fancy-code-toolbar-separator` | Toolbar separator |
348
- | `data-fancy-code-panel` | CodeMirror mount point |
349
- | `data-fancy-code-statusbar` | Status bar |
350
-
351
335
  ### Public Exports
352
336
 
353
337
  ```ts
@@ -388,12 +372,12 @@ Guidelines for AI agents (Claude Code, Copilot, etc.) working on this package.
388
372
  - Context is provided via `CodeEditorContext` and consumed with `useCodeEditor()`.
389
373
  - All root elements have `data-fancy-code-*` attributes for external CSS targeting.
390
374
 
391
- ### CodeMirror Integration
375
+ ### Editor Engine
392
376
 
393
- - The `useCodemirror` hook manages the full `EditorView` lifecycle.
394
- - Uses `Compartment` from `@codemirror/state` for hot-swapping language, theme, line numbers, word wrap, tab size, read-only, placeholder, and height constraints.
377
+ - The `useCodemirror` hook manages the editor lifecycle.
378
+ - Uses compartments for hot-swapping language, theme, line numbers, word wrap, tab size, read-only, placeholder, and height constraints.
395
379
  - External value changes are synced via `isExternalUpdate` ref to prevent onChange loops.
396
- - SSR-safe: EditorView is only created inside `useEffect`.
380
+ - SSR-safe: the editor is only created inside `useEffect`.
397
381
 
398
382
  ### Extension System
399
383
 
@@ -405,5 +389,5 @@ Guidelines for AI agents (Claude Code, Copilot, etc.) working on this package.
405
389
 
406
390
  - tsup handles the build — ESM, CJS, and `.d.ts` generation.
407
391
  - `react`, `react-dom`, and `@particle-academy/react-fancy` are external dependencies.
408
- - All CodeMirror packages are **bundled** (not external) so consumers don't need to install them.
392
+ - All editor engine packages are **bundled** (not external) so consumers don't need to install them.
409
393
  - After any change, verify with `npm run build` from the monorepo root.