@synerise/ds-code-area 1.3.28 → 1.3.30

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 (3) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/CLAUDE.md +137 -0
  3. package/package.json +12 -11
package/CHANGELOG.md CHANGED
@@ -3,6 +3,14 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [1.3.30](https://github.com/Synerise/synerise-design/compare/@synerise/ds-code-area@1.3.29...@synerise/ds-code-area@1.3.30) (2026-07-24)
7
+
8
+ **Note:** Version bump only for package @synerise/ds-code-area
9
+
10
+ ## [1.3.29](https://github.com/Synerise/synerise-design/compare/@synerise/ds-code-area@1.3.28...@synerise/ds-code-area@1.3.29) (2026-07-23)
11
+
12
+ **Note:** Version bump only for package @synerise/ds-code-area
13
+
6
14
  ## [1.3.28](https://github.com/Synerise/synerise-design/compare/@synerise/ds-code-area@1.3.27...@synerise/ds-code-area@1.3.28) (2026-07-16)
7
15
 
8
16
  **Note:** Version bump only for package @synerise/ds-code-area
package/CLAUDE.md ADDED
@@ -0,0 +1,137 @@
1
+ # CodeArea (`@synerise/ds-code-area`)
2
+
3
+ > A Monaco Editor wrapper with fullscreen mode (via `createPortal`), syntax switching, character counter, error state, label/tooltip, and customisable footer content.
4
+
5
+ ## Package structure
6
+
7
+ ```
8
+ src/
9
+ CodeArea.tsx — public-facing component; manages fullscreen state + portal
10
+ CodeArea.types.ts — all type definitions
11
+ CodeArea.styles.ts — all styled-components (also re-exported from index.ts)
12
+ CodeArea.figma.tsx — Figma Code Connect file
13
+ constants.ts — MONACO_DEFAULT_OPTIONS, DS_MONACO_THEME, DS_MONACO_THEME_NAME
14
+ index.ts — public exports
15
+ components/
16
+ CodeAreaEditor.tsx — forwardRef wrapper; handles label, counter, error, fullscreen header
17
+ CodeAreaEditorRaw.tsx — mounts <Editor> from @monaco-editor/react; owns monaco lifecycle
18
+ BottomBar.tsx — syntax select + fullscreen button + custom footer slot
19
+ ContentAbove.tsx — label + top counter row
20
+ ContentBelow.tsx — description + additional description + bottom counter + error text
21
+ FullscreenHeader.tsx — header bar shown only in fullscreen mode
22
+ AriaContainer.tsx — attaches monaco's ARIA container element to the DOM
23
+ index.ts — re-exports all components
24
+ utils/
25
+ getDefaultTexts.tsx — merges react-intl defaults with caller-supplied texts
26
+ getCharCount.ts — returns char count; undefined when over limit
27
+ calculateRequiredSpace.ts — calculates px height stolen by chrome in fullscreen
28
+ index.ts — re-exports utils
29
+ ```
30
+
31
+ ## Public exports
32
+
33
+ ### `CodeArea` (default export)
34
+
35
+ Generic component: `CodeArea<SyntaxName extends CodeAreaSyntax = CodeAreaSyntax>`.
36
+
37
+ `CodeAreaProps` = `Omit<CodeAreaEditorProps, 'toggleFullscreen' | 'isFullscreen'>` plus:
38
+
39
+ | Prop | Type | Default | Description |
40
+ |------|------|---------|-------------|
41
+ | `currentSyntax` | `CodeAreaSyntax` | — | **Required.** Active language for the editor. |
42
+ | `label` | `ReactNode` | `undefined` | Label rendered above the editor (via `FormFieldLabel`). |
43
+ | `fullscreenLabel` | `ReactNode` | `undefined` | Label shown in the fullscreen header; falls back to `label`. |
44
+ | `description` | `ReactNode` | `undefined` | Text below the editor. |
45
+ | `errorText` | `ReactNode` | `undefined` | Error message below editor; also triggers red border + background. Sets `isValid=false`. |
46
+ | `placeholder` | `ReactNode` | `undefined` | Overlay shown when editor is empty. Positioned `left: 62px` (after line numbers). |
47
+ | `counter` | `{ limit: number; placement?: 'bottom' \| 'top' }` | `undefined` | Character counter. Hard-limits input at `limit` (triggers `undo` on overflow). |
48
+ | `syntaxOptions` | `CodeAreaSyntaxOption<SyntaxName>[]` | `undefined` | Available languages. Syntax select renders in BottomBar when `length > 1` and not `readOnly`. |
49
+ | `allowFullscreen` | `boolean` | `undefined` | Shows the fullscreen button in BottomBar. |
50
+ | `readOnly` | `boolean` | `undefined` | Monaco `readOnly` + `domReadOnly`; grey background; cursor hidden. |
51
+ | `noBorder` | `boolean` | `undefined` | Removes the 1px border from the editor wrapper. |
52
+ | `height` | `string \| number` | `undefined` | Height of the wrapper. When unset, `EditorInnerWrapper` defaults to `295px`. |
53
+ | `zIndex` | `string \| number` | `undefined` | `z-index` of the fullscreen overlay. Defaults to `theme.variables['zindex-modal']`. |
54
+ | `tooltip` | `ReactNode` | `undefined` | Tooltip content shown next to the label. |
55
+ | `tooltipProps` | `TooltipProps` | `undefined` | Full tooltip configuration (merged with `tooltip`). |
56
+ | `style` | `CSSProperties` | `undefined` | Inline styles on the outermost wrapper. |
57
+ | `className` | `string` | `undefined` | Additional class on the outermost wrapper. |
58
+ | `texts` | `Partial<CodeAreaTexts>` | `undefined` | Override i18n strings (see below). |
59
+ | `value` | `string` | `undefined` | Controlled editor value (passed to `@monaco-editor/react`). |
60
+ | `defaultValue` | `string` | `undefined` | Uncontrolled initial value. |
61
+ | `options` | `EditorProps['options']` | `undefined` | Monaco editor options (merged over `MONACO_DEFAULT_OPTIONS`). |
62
+ | `loaderConfig` | `Parameters<typeof loader.config>[0]` | `undefined` | Configure the Monaco CDN/path loader. Applied once on first render. |
63
+ | `renderFooterContent` | `(state: { isFullscreen?, count?, isValid? }) => ReactNode` | `undefined` | Custom content in the right side of BottomBar. |
64
+ | `renderAdditionalDescription` | `(state: { isFullscreen?, count?, isValid? }) => ReactNode` | `undefined` | Custom content above `description`. |
65
+ | `onChange` | `EditorProps['onChange']` | `undefined` | Monaco `onChange` callback. Blocked when content exceeds `counter.limit`. |
66
+ | `onMount` | `EditorProps['onMount']` | `undefined` | Access to the editor + monaco instance after mount. |
67
+ | `beforeMount` | `EditorProps['beforeMount']` | `undefined` | Called before editor mounts; DS theme is registered here. |
68
+ | `onSyntaxChange` | `(newSyntax: SyntaxName) => void` | `undefined` | Fired when user selects a different syntax. |
69
+ | `onFullscreenChange` | `(isFullscreen: boolean) => void` | `undefined` | Fired when fullscreen is toggled. **Note: receives the *old* state**, not the new one (bug). |
70
+ | `getPopupContainer` | `(node: HTMLElement) => HTMLElement` | `getPopupContainer` from `@synerise/ds-utils` | Container for the fullscreen portal. |
71
+
72
+ ### `CodeAreaTexts` (type)
73
+
74
+ | Key | Default (react-intl) |
75
+ |-----|----------------------|
76
+ | `fullscreen` | `'Fullscreen'` (`DS.CODE-AREA.FULLSCREEN`) |
77
+ | `closeFullscreen` | `'Close fullscreen'` (`DS.CODE-AREA.CLOSE-FULLSCREEN`) |
78
+ | `fullscreenTitle` | `'Fullscreen editor'` (`DS.CODE-AREA.FULLSCREEN-TITLE`) |
79
+
80
+ ### `CodeAreaSyntaxOption<SyntaxName>` (type)
81
+
82
+ | Field | Type | Description |
83
+ |-------|------|-------------|
84
+ | `language` | `SyntaxName` | Language identifier passed to Monaco. |
85
+ | `label` | `string` (optional) | Display name in the syntax select dropdown. |
86
+
87
+ ### `CodeAreaSyntax` (type)
88
+
89
+ `'json' | 'html' | 'css' | 'typescript' | 'javascript' | string`
90
+
91
+ ### Style exports (`export * from './CodeArea.styles'`)
92
+
93
+ All styled-components are re-exported for targeted overrides: `EditorWrapper`, `BottomBar`, `Counter`, `ErrorText`, `CodeAreaWrapper`, etc.
94
+
95
+ ## Usage patterns
96
+
97
+ ```tsx
98
+ import CodeArea from '@synerise/ds-code-area';
99
+
100
+ type Syntax = 'json' | 'javascript';
101
+
102
+ <CodeArea<Syntax>
103
+ label="Query"
104
+ currentSyntax="json"
105
+ syntaxOptions={[
106
+ { language: 'json', label: 'JSON' },
107
+ { language: 'javascript', label: 'JS' },
108
+ ]}
109
+ value={code}
110
+ onChange={(val) => setCode(val ?? '')}
111
+ onSyntaxChange={setSyntax}
112
+ allowFullscreen
113
+ counter={{ limit: 5000, placement: 'bottom' }}
114
+ errorText={hasError ? 'Invalid JSON' : undefined}
115
+ height={400}
116
+ />
117
+ ```
118
+
119
+ ## Key dependencies
120
+
121
+ - `@monaco-editor/react` (4.4.6) — React wrapper for Monaco Editor; provides `<Editor>`, `loader`, and types
122
+ - `monaco-editor` (0.34.1, devDep) — types used in `constants.ts` and `CodeArea.types.ts`
123
+ - `react-intl` — **required peer dep** for default `texts`; app must have `<IntlProvider>`
124
+ - `@synerise/ds-form-field` (`FormFieldLabel`) — renders `label` + `tooltip` above the editor
125
+ - `@synerise/ds-inline-edit` (`InlineSelect`) — syntax switcher in BottomBar
126
+
127
+ ## Implementation notes
128
+
129
+ - **Fullscreen uses `createPortal`**: when `isFullscreen=true`, a second `<CodeAreaEditor>` is mounted via portal into `getPopupContainer(wrapperRef.current)`. The in-place editor remains mounted with `isFullscreen={false}` always. This means two Monaco instances exist simultaneously during fullscreen.
130
+ - **`onFullscreenChange` receives the old state**: `onFullscreenChange && onFullscreenChange(isFullscreen)` is called before `setIsFullscreen` — the callback gets the value *before* the toggle (likely a bug).
131
+ - **Counter hard-limit**: when `value.length > counter.limit`, `CodeAreaEditorRaw` triggers `'undo'` on the Monaco instance directly. The `onChange` callback is not called for over-limit input.
132
+ - **`isValid` logic**: `isValid` starts as `true`, is set to `false` when `errorText` is truthy (via `useEffect`), and is also set to `false` when Monaco reports markers (lint/parse errors). Both paths independently drive the error state.
133
+ - **Monaco theme**: `DS_MONACO_THEME` (`'DSTheme'`) is registered in `beforeMount` and uses a transparent background so the wrapper's background colour shows through.
134
+ - **`loaderConfig` is one-shot**: a `loaderConfigSet` ref prevents calling `loader.config()` more than once per component instance — changing `loaderConfig` after mount has no effect.
135
+ - **`placeholder` offset**: positioned `left: 62px` to align with the editor text column after Monaco's line-number gutter. Adjust if `options.lineNumbers` is set to `'off'`.
136
+ - **BottomBar visibility**: shown when at least one of `isSyntaxSelectVisible`, `allowFullscreen && !isFullscreen`, or `renderFooterContent` is truthy.
137
+ - **AriaContainer**: Monaco's accessibility tree is redirected to a detached `<div>` created in `useMemo` and attached to the DOM via `<AriaContainer>`. This prevents Monaco's ARIA announcements from polluting the page structure.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synerise/ds-code-area",
3
- "version": "1.3.28",
3
+ "version": "1.3.30",
4
4
  "description": "CodeArea UI Component for the Synerise Design System",
5
5
  "license": "ISC",
6
6
  "repository": "Synerise/synerise-design",
@@ -17,6 +17,7 @@
17
17
  "files": [
18
18
  "/dist",
19
19
  "CHANGELOG.md",
20
+ "CLAUDE.md",
20
21
  "README.md",
21
22
  "package.json",
22
23
  "LICENSE.md"
@@ -42,15 +43,15 @@
42
43
  "types": "dist/index.d.ts",
43
44
  "dependencies": {
44
45
  "@monaco-editor/react": "4.4.6",
45
- "@synerise/ds-button": "^1.5.34",
46
- "@synerise/ds-core": "^1.13.0",
47
- "@synerise/ds-form-field": "^1.3.23",
48
- "@synerise/ds-icon": "^1.18.4",
49
- "@synerise/ds-inline-edit": "^1.1.47",
50
- "@synerise/ds-loader": "^1.0.17",
51
- "@synerise/ds-tooltip": "^1.5.3",
52
- "@synerise/ds-typography": "^1.1.26",
53
- "@synerise/ds-utils": "^1.10.1"
46
+ "@synerise/ds-button": "^1.5.35",
47
+ "@synerise/ds-core": "^1.13.1",
48
+ "@synerise/ds-form-field": "^1.3.24",
49
+ "@synerise/ds-icon": "^1.18.5",
50
+ "@synerise/ds-inline-edit": "^1.1.49",
51
+ "@synerise/ds-loader": "^1.0.18",
52
+ "@synerise/ds-tooltip": "^1.5.4",
53
+ "@synerise/ds-typography": "^1.1.27",
54
+ "@synerise/ds-utils": "^1.10.2"
54
55
  },
55
56
  "peerDependencies": {
56
57
  "@synerise/ds-core": "*",
@@ -63,5 +64,5 @@
63
64
  "monaco-editor": "0.34.1",
64
65
  "vitest": "4"
65
66
  },
66
- "gitHead": "a81ab6519d49a3dea9c0cfebcdc9104cbb4f4226"
67
+ "gitHead": "018414e0d7ffd102a07f8aa35fa2e2d3d4ed19e2"
67
68
  }