@qoretechnologies/reqraft 0.10.54 → 0.10.55-pr.115.g24a94bf
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/.claude/CLAUDE.md +25 -0
- package/.tasks/INDEX.md +1 -0
- package/.tasks/STORY_NETWORK_ISOLATION.md +98 -0
- package/README.md +1 -1
- package/design/FORM_ENGINE_EXPRESSIONS.md +110 -0
- package/design/FORM_ENGINE_FIELD_MIGRATION.md +155 -1
- package/design/RENDER_EXPRESSION_TRANSPORT.md +76 -10
- package/design/SMART_EDITOR_UX.md +21 -0
- package/dist/components/dpqlEditor/DpqlEditor.d.ts.map +1 -1
- package/dist/components/dpqlEditor/DpqlEditor.js +3 -3
- package/dist/components/dpqlEditor/DpqlEditor.js.map +1 -1
- package/dist/components/dpqlEditor/dpqlHelpers.d.ts +6 -0
- package/dist/components/dpqlEditor/dpqlHelpers.d.ts.map +1 -1
- package/dist/components/dpqlEditor/dpqlHelpers.js +21 -2
- package/dist/components/dpqlEditor/dpqlHelpers.js.map +1 -1
- package/dist/components/dpqlEditor/dpqlProbe.d.ts +37 -0
- package/dist/components/dpqlEditor/dpqlProbe.d.ts.map +1 -0
- package/dist/components/dpqlEditor/dpqlProbe.js +203 -0
- package/dist/components/dpqlEditor/dpqlProbe.js.map +1 -0
- package/dist/components/dpqlEditor/dpqlTags.d.ts +8 -0
- package/dist/components/dpqlEditor/dpqlTags.d.ts.map +1 -1
- package/dist/components/dpqlEditor/dpqlTags.js +5 -1
- package/dist/components/dpqlEditor/dpqlTags.js.map +1 -1
- package/dist/components/dpqlEditor/index.d.ts +4 -0
- package/dist/components/dpqlEditor/index.d.ts.map +1 -1
- package/dist/components/dpqlEditor/index.js +5 -1
- package/dist/components/dpqlEditor/index.js.map +1 -1
- package/dist/components/dpqlEditor/types.d.ts +42 -2
- package/dist/components/dpqlEditor/types.d.ts.map +1 -1
- package/dist/components/dpqlEditor/types.js +0 -4
- package/dist/components/dpqlEditor/types.js.map +1 -1
- package/dist/components/dpqlEditor/useDpqlProbe.d.ts +4 -0
- package/dist/components/dpqlEditor/useDpqlProbe.d.ts.map +1 -0
- package/dist/components/dpqlEditor/useDpqlProbe.js +29 -0
- package/dist/components/dpqlEditor/useDpqlProbe.js.map +1 -0
- package/dist/components/dpqlEditor/useDpqlSession.d.ts +5 -2
- package/dist/components/dpqlEditor/useDpqlSession.d.ts.map +1 -1
- package/dist/components/dpqlEditor/useDpqlSession.js +8 -2
- package/dist/components/dpqlEditor/useDpqlSession.js.map +1 -1
- package/dist/components/form/engine/CompactRow.d.ts.map +1 -1
- package/dist/components/form/engine/CompactRow.js +192 -45
- package/dist/components/form/engine/CompactRow.js.map +1 -1
- package/dist/components/form/engine/CompactToolbar.d.ts.map +1 -1
- package/dist/components/form/engine/CompactToolbar.js +5 -2
- package/dist/components/form/engine/CompactToolbar.js.map +1 -1
- package/dist/components/form/engine/FormEngine.d.ts +160 -12
- package/dist/components/form/engine/FormEngine.d.ts.map +1 -1
- package/dist/components/form/engine/FormEngine.js +380 -78
- package/dist/components/form/engine/FormEngine.js.map +1 -1
- package/dist/components/form/engine/FormFieldsSkeleton.d.ts +48 -0
- package/dist/components/form/engine/FormFieldsSkeleton.d.ts.map +1 -0
- package/dist/components/form/engine/FormFieldsSkeleton.js +38 -0
- package/dist/components/form/engine/FormFieldsSkeleton.js.map +1 -0
- package/dist/components/form/engine/OptionFieldMessages.d.ts +17 -2
- package/dist/components/form/engine/OptionFieldMessages.d.ts.map +1 -1
- package/dist/components/form/engine/OptionFieldMessages.js +73 -12
- package/dist/components/form/engine/OptionFieldMessages.js.map +1 -1
- package/dist/components/form/engine/_structuredData/SchemaDataView.d.ts.map +1 -1
- package/dist/components/form/engine/_structuredData/SchemaDataView.js +7 -1
- package/dist/components/form/engine/_structuredData/SchemaDataView.js.map +1 -1
- package/dist/components/form/engine/compactToolbarContext.d.ts +1 -0
- package/dist/components/form/engine/compactToolbarContext.d.ts.map +1 -1
- package/dist/components/form/engine/readFirst.d.ts +42 -1
- package/dist/components/form/engine/readFirst.d.ts.map +1 -1
- package/dist/components/form/engine/readFirst.js +74 -7
- package/dist/components/form/engine/readFirst.js.map +1 -1
- package/dist/components/form/engine/rendererTypes.d.ts +13 -0
- package/dist/components/form/engine/rendererTypes.d.ts.map +1 -1
- package/dist/components/form/engine/rendererTypes.js.map +1 -1
- package/dist/components/form/engine/rowMenuContext.d.ts +78 -0
- package/dist/components/form/engine/rowMenuContext.d.ts.map +1 -0
- package/dist/components/form/engine/rowMenuContext.js +103 -0
- package/dist/components/form/engine/rowMenuContext.js.map +1 -0
- package/dist/components/form/engine/typeChoices.d.ts +42 -0
- package/dist/components/form/engine/typeChoices.d.ts.map +1 -0
- package/dist/components/form/engine/typeChoices.js +31 -0
- package/dist/components/form/engine/typeChoices.js.map +1 -0
- package/dist/components/form/expressions/DpqlRendering.d.ts +26 -0
- package/dist/components/form/expressions/DpqlRendering.d.ts.map +1 -0
- package/dist/components/form/expressions/DpqlRendering.js +53 -0
- package/dist/components/form/expressions/DpqlRendering.js.map +1 -0
- package/dist/components/form/expressions/ExpressionField.d.ts +7 -1
- package/dist/components/form/expressions/ExpressionField.d.ts.map +1 -1
- package/dist/components/form/expressions/ExpressionField.js +203 -45
- package/dist/components/form/expressions/ExpressionField.js.map +1 -1
- package/dist/components/form/expressions/argumentPresence.d.ts +84 -0
- package/dist/components/form/expressions/argumentPresence.d.ts.map +1 -0
- package/dist/components/form/expressions/argumentPresence.js +217 -0
- package/dist/components/form/expressions/argumentPresence.js.map +1 -0
- package/dist/components/form/expressions/builder/argumentLabel.d.ts.map +1 -1
- package/dist/components/form/expressions/builder/argumentLabel.js +9 -4
- package/dist/components/form/expressions/builder/argumentLabel.js.map +1 -1
- package/dist/components/form/expressions/builder/index.d.ts +15 -2
- package/dist/components/form/expressions/builder/index.d.ts.map +1 -1
- package/dist/components/form/expressions/builder/index.js +21 -65
- package/dist/components/form/expressions/builder/index.js.map +1 -1
- package/dist/components/form/expressions/builder/renderTemplate.d.ts +4 -1
- package/dist/components/form/expressions/builder/renderTemplate.d.ts.map +1 -1
- package/dist/components/form/expressions/builder/renderTemplate.js +10 -67
- package/dist/components/form/expressions/builder/renderTemplate.js.map +1 -1
- package/dist/components/form/expressions/dpqlMockLanguage.d.ts +76 -0
- package/dist/components/form/expressions/dpqlMockLanguage.d.ts.map +1 -0
- package/dist/components/form/expressions/dpqlMockLanguage.js +525 -0
- package/dist/components/form/expressions/dpqlMockLanguage.js.map +1 -0
- package/dist/components/form/expressions/dpqlMockLsp.d.ts +31 -2
- package/dist/components/form/expressions/dpqlMockLsp.d.ts.map +1 -1
- package/dist/components/form/expressions/dpqlMockLsp.js +86 -80
- package/dist/components/form/expressions/dpqlMockLsp.js.map +1 -1
- package/dist/components/form/expressions/mockExpressions.d.ts.map +1 -1
- package/dist/components/form/expressions/mockExpressions.js +8 -4
- package/dist/components/form/expressions/mockExpressions.js.map +1 -1
- package/dist/components/form/expressions/renderExpressionToText.d.ts +1 -1
- package/dist/components/form/expressions/renderExpressionToText.d.ts.map +1 -1
- package/dist/components/form/expressions/renderExpressionToText.js +95 -19
- package/dist/components/form/expressions/renderExpressionToText.js.map +1 -1
- package/dist/components/form/expressions/types.d.ts +7 -0
- package/dist/components/form/expressions/types.d.ts.map +1 -1
- package/dist/components/form/expressions/useRenderExpression.d.ts +7 -16
- package/dist/components/form/expressions/useRenderExpression.d.ts.map +1 -1
- package/dist/components/form/expressions/useRenderExpression.js +50 -126
- package/dist/components/form/expressions/useRenderExpression.js.map +1 -1
- package/dist/components/form/fields/Field.d.ts.map +1 -1
- package/dist/components/form/fields/Field.js +3 -1
- package/dist/components/form/fields/Field.js.map +1 -1
- package/dist/components/form/fields/allowed-values/AllowedValues.d.ts +11 -1
- package/dist/components/form/fields/allowed-values/AllowedValues.d.ts.map +1 -1
- package/dist/components/form/fields/allowed-values/AllowedValues.js +14 -2
- package/dist/components/form/fields/allowed-values/AllowedValues.js.map +1 -1
- package/dist/components/form/fields/auto/AutoFormField.d.ts.map +1 -1
- package/dist/components/form/fields/auto/AutoFormField.js +91 -28
- package/dist/components/form/fields/auto/AutoFormField.js.map +1 -1
- package/dist/components/form/fields/date/Date.d.ts +1 -1
- package/dist/components/form/fields/date/Date.d.ts.map +1 -1
- package/dist/components/form/fields/date/Date.js +16 -2
- package/dist/components/form/fields/date/Date.js.map +1 -1
- package/dist/components/form/fields/long-string/LongString.d.ts.map +1 -1
- package/dist/components/form/fields/long-string/LongString.js +14 -2
- package/dist/components/form/fields/long-string/LongString.js.map +1 -1
- package/dist/components/form/fields/rich-text/RichText.d.ts +35 -2
- package/dist/components/form/fields/rich-text/RichText.d.ts.map +1 -1
- package/dist/components/form/fields/rich-text/RichText.js +153 -12
- package/dist/components/form/fields/rich-text/RichText.js.map +1 -1
- package/dist/components/form/fields/template/ReadOnlyTemplateTag.d.ts +2 -1
- package/dist/components/form/fields/template/ReadOnlyTemplateTag.d.ts.map +1 -1
- package/dist/components/form/fields/template/ReadOnlyTemplateTag.js +3 -2
- package/dist/components/form/fields/template/ReadOnlyTemplateTag.js.map +1 -1
- package/dist/components/form/fields/template/TemplateField.d.ts +34 -2
- package/dist/components/form/fields/template/TemplateField.d.ts.map +1 -1
- package/dist/components/form/fields/template/TemplateField.js +606 -58
- package/dist/components/form/fields/template/TemplateField.js.map +1 -1
- package/dist/components/form/index.d.ts +1 -0
- package/dist/components/form/index.d.ts.map +1 -1
- package/dist/components/form/index.js +1 -0
- package/dist/components/form/index.js.map +1 -1
- package/dist/components/smartEditor/SmartEditor.d.ts.map +1 -1
- package/dist/components/smartEditor/SmartEditor.js +29 -8
- package/dist/components/smartEditor/SmartEditor.js.map +1 -1
- package/dist/components/smartEditor/__fixtures__/mockLspServer.d.ts +8 -0
- package/dist/components/smartEditor/__fixtures__/mockLspServer.d.ts.map +1 -1
- package/dist/components/smartEditor/__fixtures__/mockLspServer.js +53 -10
- package/dist/components/smartEditor/__fixtures__/mockLspServer.js.map +1 -1
- package/dist/components/smartEditor/useLspSession.d.ts +5 -1
- package/dist/components/smartEditor/useLspSession.d.ts.map +1 -1
- package/dist/components/smartEditor/useLspSession.js +16 -2
- package/dist/components/smartEditor/useLspSession.js.map +1 -1
- package/dist/helpers/dpqlDetection.d.ts +58 -0
- package/dist/helpers/dpqlDetection.d.ts.map +1 -0
- package/dist/helpers/dpqlDetection.js +164 -0
- package/dist/helpers/dpqlDetection.js.map +1 -0
- package/dist/helpers/optionUiTypes.d.ts +19 -3
- package/dist/helpers/optionUiTypes.d.ts.map +1 -1
- package/dist/helpers/optionUiTypes.js +20 -1
- package/dist/helpers/optionUiTypes.js.map +1 -1
- package/dist/helpers/options.d.ts +37 -0
- package/dist/helpers/options.d.ts.map +1 -1
- package/dist/helpers/options.js +78 -1
- package/dist/helpers/options.js.map +1 -1
- package/dist/helpers/templateItems.d.ts +47 -0
- package/dist/helpers/templateItems.d.ts.map +1 -0
- package/dist/helpers/templateItems.js +88 -0
- package/dist/helpers/templateItems.js.map +1 -0
- package/dist/helpers/templateText.d.ts +37 -0
- package/dist/helpers/templateText.d.ts.map +1 -0
- package/dist/helpers/templateText.js +64 -0
- package/dist/helpers/templateText.js.map +1 -0
- package/dist/helpers/templates.d.ts +30 -12
- package/dist/helpers/templates.d.ts.map +1 -1
- package/dist/helpers/templates.js +91 -33
- package/dist/helpers/templates.js.map +1 -1
- package/dist/helpers/validations.d.ts +1 -1
- package/dist/helpers/validations.d.ts.map +1 -1
- package/dist/helpers/validations.js +68 -12
- package/dist/helpers/validations.js.map +1 -1
- package/dist/hooks/useArgSchema.d.ts +2 -1
- package/dist/hooks/useArgSchema.d.ts.map +1 -1
- package/dist/hooks/useFetch/useFetch.d.ts +3 -1
- package/dist/hooks/useFetch/useFetch.d.ts.map +1 -1
- package/dist/hooks/useFetch/useFetch.js +47 -9
- package/dist/hooks/useFetch/useFetch.js.map +1 -1
- package/dist/hooks/useTemplates.d.ts +20 -0
- package/dist/hooks/useTemplates.d.ts.map +1 -1
- package/dist/hooks/useTemplates.js +34 -2
- package/dist/hooks/useTemplates.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/stories/storyNetwork.d.ts +36 -0
- package/dist/stories/storyNetwork.d.ts.map +1 -0
- package/dist/stories/storyNetwork.js +82 -0
- package/dist/stories/storyNetwork.js.map +1 -0
- package/dist/utils/fetch.d.ts +151 -1
- package/dist/utils/fetch.d.ts.map +1 -1
- package/dist/utils/fetch.js +256 -44
- package/dist/utils/fetch.js.map +1 -1
- package/dist/utils/lspClient.d.ts +6 -0
- package/dist/utils/lspClient.d.ts.map +1 -1
- package/dist/utils/lspClient.js +62 -11
- package/dist/utils/lspClient.js.map +1 -1
- package/dist/utils/websocket.d.ts +6 -0
- package/dist/utils/websocket.d.ts.map +1 -1
- package/dist/utils/websocket.js +15 -7
- package/dist/utils/websocket.js.map +1 -1
- package/package.json +2 -2
- package/src/components/dpqlEditor/DpqlEditor.stories.tsx +3 -119
- package/src/components/dpqlEditor/DpqlEditor.tsx +5 -2
- package/src/components/dpqlEditor/dpqlHelpers.ts +20 -1
- package/src/components/dpqlEditor/dpqlProbe.ts +165 -0
- package/src/components/dpqlEditor/dpqlTags.ts +13 -0
- package/src/components/dpqlEditor/index.ts +4 -0
- package/src/components/dpqlEditor/types.ts +38 -2
- package/src/components/dpqlEditor/useDpqlProbe.ts +33 -0
- package/src/components/dpqlEditor/useDpqlSession.ts +20 -4
- package/src/components/form/engine/CompactRow.tsx +240 -51
- package/src/components/form/engine/CompactToolbar.tsx +10 -3
- package/src/components/form/engine/FormEngine.stories.tsx +431 -124
- package/src/components/form/engine/FormEngine.tsx +508 -90
- package/src/components/form/engine/FormFieldsSkeleton.tsx +76 -0
- package/src/components/form/engine/OptionFieldMessages.tsx +103 -12
- package/src/components/form/engine/_structuredData/SchemaDataView.tsx +11 -0
- package/src/components/form/engine/compactToolbarContext.ts +1 -1
- package/src/components/form/engine/readFirst.ts +86 -7
- package/src/components/form/engine/rendererTypes.ts +12 -0
- package/src/components/form/engine/rowMenuContext.ts +159 -0
- package/src/components/form/engine/typeChoices.ts +61 -0
- package/src/components/form/expressions/DpqlRendering.tsx +85 -0
- package/src/components/form/expressions/ExpressionField.stories.tsx +826 -48
- package/src/components/form/expressions/ExpressionField.tsx +266 -54
- package/src/components/form/expressions/argumentPresence.ts +213 -0
- package/src/components/form/expressions/builder/ExpressionBuilder.stories.tsx +31 -14
- package/src/components/form/expressions/builder/argumentLabel.tsx +10 -4
- package/src/components/form/expressions/builder/index.tsx +39 -81
- package/src/components/form/expressions/builder/renderTemplate.tsx +23 -56
- package/src/components/form/expressions/dpqlMockLanguage.ts +565 -0
- package/src/components/form/expressions/dpqlMockLsp.ts +109 -83
- package/src/components/form/expressions/mockExpressions.ts +8 -4
- package/src/components/form/expressions/renderExpressionToText.ts +112 -22
- package/src/components/form/expressions/types.ts +7 -0
- package/src/components/form/expressions/useRenderExpression.ts +43 -127
- package/src/components/form/fields/Field.tsx +3 -2
- package/src/components/form/fields/allowed-values/AllowedValues.tsx +13 -2
- package/src/components/form/fields/auto/AutoFormField.stories.tsx +85 -18
- package/src/components/form/fields/auto/AutoFormField.tsx +90 -20
- package/src/components/form/fields/date/Date.tsx +17 -1
- package/src/components/form/fields/long-string/LongString.tsx +15 -3
- package/src/components/form/fields/rich-text/RichText.tsx +235 -30
- package/src/components/form/fields/template/ReadOnlyTemplateTag.tsx +4 -2
- package/src/components/form/fields/template/TemplateField.stories.tsx +93 -14
- package/src/components/form/fields/template/TemplateField.tsx +825 -131
- package/src/components/form/index.tsx +1 -0
- package/src/components/log/Log.stories.tsx +2 -1
- package/src/components/smartEditor/SmartEditor.tsx +41 -9
- package/src/components/smartEditor/__fixtures__/mockLspServer.ts +52 -3
- package/src/components/smartEditor/useLspSession.ts +21 -3
- package/src/helpers/dpqlDetection.ts +209 -0
- package/src/helpers/optionUiTypes.ts +22 -0
- package/src/helpers/options.ts +70 -0
- package/src/helpers/templateItems.ts +81 -0
- package/src/helpers/templateText.ts +92 -0
- package/src/helpers/templates.ts +94 -41
- package/src/helpers/validations.ts +79 -24
- package/src/hooks/useFetch/useFetch.stories.tsx +6 -5
- package/src/hooks/useFetch/useFetch.tsx +53 -7
- package/src/hooks/useStorage/useStorage.stories.tsx +2 -1
- package/src/hooks/useTemplates.ts +41 -0
- package/src/hooks/useWebSocket/useWebsocket.stories.tsx +2 -1
- package/src/index.tsx +14 -1
- package/src/stores/currentUser/currentUser.stories.tsx +2 -1
- package/src/stories/storyNetwork.ts +92 -0
- package/src/utils/fetch.ts +311 -21
- package/src/utils/lspClient.ts +68 -11
- package/src/utils/websocket.ts +20 -9
package/.claude/CLAUDE.md
CHANGED
|
@@ -167,6 +167,7 @@ yarn build:test # Type-check without emit
|
|
|
167
167
|
|
|
168
168
|
- `yarn precheck` runs: lint → test → build:test:prod
|
|
169
169
|
- `pre-push` hook enforces: `build:test:prod`, `lint`, `test`
|
|
170
|
+
- CI (`.github/workflows/tests.yml`) runs precheck, build and the full story suite for PRs into `develop` **and** for every push to `develop`. GitHub skips `pull_request` workflows while a PR has merge conflicts, so a conflicting PR gets no test runs until it is rebased or merged up
|
|
170
171
|
- Branch naming: always start with the issue number, e.g. `feature/49_pooled-connections`
|
|
171
172
|
|
|
172
173
|
### Versioning — every PR to `develop` MUST bump the version
|
|
@@ -201,6 +202,26 @@ yarn build:test # Type-check without emit
|
|
|
201
202
|
- Stories are co-located alongside source: `src/hooks/useFetch/useFetch.stories.tsx`
|
|
202
203
|
- Storybook port: **6008**
|
|
203
204
|
- Story + interaction tests run on **Vitest browser mode** (Playwright/Chromium): `yarn test:stories [file-substring]`. Run `yarn install-playwright` once first.
|
|
205
|
+
- **Story network — mocks must follow the instance, and stories must not share connections.**
|
|
206
|
+
- Build every mock URL with `storyApiUrl(path)` / `storySocketUrl(path)` from
|
|
207
|
+
`src/stories/storyNetwork.ts`, never a hard-coded `https://hq.qoretechnologies.com:8092/…`.
|
|
208
|
+
Both mock layers match on host (storybook-addon-mock keys on `host + pathname`,
|
|
209
|
+
mock-socket on the URL minus its query), so a hard-coded host silently stops matching
|
|
210
|
+
when `REACT_APP_QORUS_INSTANCE` is overridden and the request goes to the real network.
|
|
211
|
+
- Requests components make on their own (FormEngine's `system/qorus-type-info`, the
|
|
212
|
+
expression catalogue `useExpressions` fetches whenever functions are allowed, the
|
|
213
|
+
reconnect probe `system/pid`) are mocked for every story via `GLOBAL_STORY_MOCK_DATA`
|
|
214
|
+
(`parameters.mockAddonConfigs.globalMockData`). Add new ones there, not per story file.
|
|
215
|
+
- A mock `response` must be an object, array or function — a bare number or string fails
|
|
216
|
+
the addon's validation and the entry is silently never matched (`TStoryMockResponse`
|
|
217
|
+
enforces this at compile time). The addon compares query-parameter *keys* only, so
|
|
218
|
+
`system?action=a&context=x` also answers `system?action=b&context=y`.
|
|
219
|
+
- `.storybook/preview.tsx` resets the shared LSP connections and the expression render
|
|
220
|
+
client before every story. Do not add per-file `ReqraftWebSocketsManager.closeAll()`
|
|
221
|
+
calls for LSP isolation.
|
|
222
|
+
- CI reaches the live hq instance with a valid token, so a story that leaks a real
|
|
223
|
+
request can pass in CI and hang locally. When a story passes in CI but times out on
|
|
224
|
+
your machine, look for an unmocked request before anything else.
|
|
204
225
|
- **Visual regression via Qlip** (not Chromatic): the story run captures snapshots through the `qlip` Vitest plugin. Upload is gated on `QLIP_UPLOAD_TOKEN` (`vitest.config.ts`), so **local runs capture but never upload** — PNGs land in `qlip/screenshots/<ts>/stories/auto/<StoryId>.png` (gitignored); read the PNG to verify a visual change. CI (`.github/workflows/tests.yml`) sets the token and uploads a build for dashboard review. The full visual-change flow + the `qlip` MCP review skill live in the imported `stacks/frontend/FRONTEND.md`.
|
|
205
226
|
|
|
206
227
|
## Code Patterns & Conventions
|
|
@@ -260,6 +281,10 @@ yarn build:test # Type-check without emit
|
|
|
260
281
|
| `query()` returning stale data | Pass `cache: false`; POST/DELETE bypass cache automatically |
|
|
261
282
|
| Heartbeat noise in logs | Filter `ev.data === 'pong'` — already done inside `useReqraftWebSocket` |
|
|
262
283
|
| Storage path collisions | Use `includeAppPrefix: true` in `useReqraftStorage` to namespace per app |
|
|
284
|
+
| Story shows FormEngine's loading skeleton / "Connecting to language server…" forever | An unmocked request or a connection inherited from an earlier story — see "Story network" above |
|
|
285
|
+
| "No Preview — Sorry, but you either have no stories…" in a story failure | Not a registration failure: addon-vitest injects Storybook's hidden preview body into every test page, and a failed query's DOM dump prints it. Read the assertion above the dump |
|
|
286
|
+
| A story run stops reporting and never times out (no failure, no output) | The page's main thread is blocked, so the in-page 30s test timer cannot fire — usually a synchronous render loop inside `act()`. Find the story with `--reporter=verbose` (the last ✓ is the one before it), then give Chromium `launchOptions: { args: ['--remote-debugging-port=9333'] }` in `vitest.config.ts` locally, enable `Debugger` over CDP BEFORE the freeze, and `Debugger.pause` once `Runtime.evaluate` stops answering to get the stack. Revert the config afterwards |
|
|
287
|
+
| `yarn test:stories` hangs before any test runs (the port message is incidental) | Seen when the checkout path contains `+` — e.g. an auto-named `.claude/worktrees/fix+name` — while the same tree at a `+`-free path runs normally. Use a path without `+` |
|
|
263
288
|
|
|
264
289
|
## File Reference
|
|
265
290
|
|
package/.tasks/INDEX.md
CHANGED
|
@@ -58,6 +58,7 @@ needs phase 1.
|
|
|
58
58
|
| [RENDER_EXPRESSION_LSP](./RENDER_EXPRESSION_LSP.md) | done pending user verify, branch `feature/render-expression-lsp` — server deployed + live-verified end-to-end 2026-06-10 (final gate 201/201 storybook, 268/268 jest, browser proof of server rendering) | **8th.** Server "Explain" over the LSP: new `dpql/renderExpression` in `QorusLspWebSocketHandler.qc` + `useRenderExpression` swap. Closes EXPRESSION_BUILDER_REPORT Phase D. Design: `design/RENDER_EXPRESSION_TRANSPORT.md`. |
|
|
59
59
|
| [FIELD_STACK_REPORT](./FIELD_STACK_REPORT.md) | done pending user verify (uncommitted) — final gate 234/234 storybook (incl. 37 ported Template/Auto plays), 268/268 jest | **9th.** Verbatim re-port of the IDE's `Field/template.tsx` + `Field/auto.tsx` (the operand layer under the ported builder) + their IDE stories, replacing the from-scratch TemplateField/AutoFormField; closes the `isFunction` operand-flow gap (behavioral difference #4 in EXPRESSION_BUILDER_REPORT). Supersedes the from-scratch implementation from REQRAFT_AUTO_FIELD (its stories/assertions are kept and reconciled). |
|
|
60
60
|
| [BRANCH_REMEDIATION](./BRANCH_REMEDIATION.md) | done pending user verify (uncommitted) — jest 268→356, plays 241→255, lint/tsc clean | **10th.** Burn-down of the 2026-06-10 full-branch audit: tests/stories/API/comment-voice remediation + behavior fixes (Select modal-click collapse, edge-triggered Url, ReqraftLspClient rename, CI auth wiring). Ledger: gitignored `SWEEP.local.md`. |
|
|
61
|
+
| [STORY_NETWORK_ISOLATION](./STORY_NETWORK_ISOLATION.md) | done pending user verify, folded into `fix/per-field-templates` (PR #115), not pushed | **Standalone.** ExpressionField stories failed off-network on `develop` (passed in CI only because CI reaches the live instance): LSP connections leaking across stories, an unhandled socket give-up in `LspSharedConnection`, unmocked background requests, and mock URLs hard-coded to the hq host. |
|
|
61
62
|
| [TEMPLATE_TOKEN_GRAMMAR](./TEMPLATE_TOKEN_GRAMMAR.md) | committed `0ef167c`, in PR (branch `bugfix/template-token-grammar`) — user-verified 2026-08-27; 13/13 unit, 21/21 template plays, qlip PNGs read | **11th (bugfix).** Braced `$data:{…}` state-output refs rehydrate as raw text: canonical token grammar + strict whole-token check + TemplateField renders whole-token values as the picker chip. Twin fix applied in qorus-ide the same day; ships as a normal per-PR patch release (`0.10.37`). |
|
|
62
63
|
| [EXPRESSION_FIELD_SEAMS](./EXPRESSION_FIELD_SEAMS.md) | committed `f5fb2ee`, pushed (branch `bugfix/116_expression-field-seams`) — user-verified 2026-09-07; PR not yet opened | **12th (bugfix).** The `extraActions` seam stopped one hop short of the `ExpressionField` shell hosts mount, and the builder's operand `TemplateField` mounts dropped it again — qorus-ide lost its AI-assist button on every expression card when it adopted the shell ([#116](https://github.com/qoretechnologies/toolkit-react/issues/116)). Forward it through both hops; pin with a nested-operand story; ships as a per-PR patch (`0.10.51`; re-based onto `4860e6e` after #114 published 0.10.50). |
|
|
63
64
|
| [EXPORT_EXPRESSION_BUILDER](./EXPORT_EXPRESSION_BUILDER.md) | committed `0eea9e7`, pushed, PR open (branch `feature/119_export-expression-builder`) | **13th (surface fix).** The barrel exported the `ExpressionField` shell but not the bare `ExpressionBuilder`, so a host mirroring the library's root/nested rule had to deep-import `dist/…/builder` ([#119](https://github.com/qoretechnologies/toolkit-react/issues/119)). Export + a barrel test; ships as `0.10.53`. |
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Story network isolation — ExpressionField stories fail off-network
|
|
2
|
+
|
|
3
|
+
**Status:** done pending user verify — folded into `fix/per-field-templates`
|
|
4
|
+
(PR #115) so every open reqraft fix ships in one PR; not yet pushed.
|
|
5
|
+
Originally built and verified on `develop` (stories 479/479, unit 930/930,
|
|
6
|
+
off-network), then re-verified on the combined branch.
|
|
7
|
+
|
|
8
|
+
## Symptom
|
|
9
|
+
|
|
10
|
+
`yarn test:stories ExpressionField` failed 6 of 8 on `develop` locally, while the
|
|
11
|
+
same file passed in CI (run 34250300001, 2026-09-08). Siblings failed the same
|
|
12
|
+
way: FormEngineRemote 11/11, AutoFormField 1, SchemaDefinitionField 2,
|
|
13
|
+
useWebsocket 3, TemplateField 1.
|
|
14
|
+
|
|
15
|
+
## Root causes
|
|
16
|
+
|
|
17
|
+
1. **An LSP connection outlived the story that opened it.** `useRenderExpression`
|
|
18
|
+
holds the endpoint's `LspSharedConnection` for the page lifetime. `Default`
|
|
19
|
+
(no mock LSP) dialled the real instance; `Empty` / `Text Mode` then joined that
|
|
20
|
+
connection's never-settling handshake, so their mock LSP was never dialled
|
|
21
|
+
("Connecting to language server…" forever). Each passes when run alone.
|
|
22
|
+
2. **The shared connection had no way out of a dead socket** (product bug). No
|
|
23
|
+
`onReconnectFailed` handling: a first handshake whose socket gave up stayed
|
|
24
|
+
pending forever for every later client; one that had completed kept reporting
|
|
25
|
+
the dead socket as ready. `close()` also abandoned an in-flight handshake, and
|
|
26
|
+
`release()` could evict a connection that had replaced its own after a reset.
|
|
27
|
+
3. **Requests components make on their own were unmocked.** FormEngine gates on
|
|
28
|
+
`system/qorus-type-info`; TemplateField's "Use Expression" waits on the
|
|
29
|
+
expression catalogue; every `ReqraftWebSocket` reconnect awaits a `system/pid`
|
|
30
|
+
probe. Against an unreachable instance none settles — the form stays a
|
|
31
|
+
skeleton, the menu entry never appears, the socket never reconnects or gives
|
|
32
|
+
up. CI's live instance answered all three, which is why CI stayed green.
|
|
33
|
+
4. **Mock URLs hard-coded the hq host.** Both mock layers match on host, so
|
|
34
|
+
overriding `REACT_APP_QORUS_INSTANCE` silently disabled every mock.
|
|
35
|
+
|
|
36
|
+
## Fix
|
|
37
|
+
|
|
38
|
+
- `src/utils/lspClient.ts` — give-up / close settle the handshake and forget the
|
|
39
|
+
socket; retry paths guarded by identity; `release()` only evicts itself.
|
|
40
|
+
4 new unit tests + the disconnect-mid-handshake test now asserts the rejection.
|
|
41
|
+
- `src/stories/storyNetwork.ts` — `STORY_QORUS_INSTANCE`, `storyApiUrl`,
|
|
42
|
+
`storySocketUrl`, `GLOBAL_STORY_MOCK_DATA` (types catalogue, empty expression
|
|
43
|
+
catalogue, reconnect probe),
|
|
44
|
+
`TStoryMockResponse` (the addon silently ignores non-object responses).
|
|
45
|
+
- `.storybook/preview.tsx` — `mockAddonConfigs.globalMockData`, per-story LSP
|
|
46
|
+
reset in a project `beforeEach`; `.storybook/vitest.setup.ts` mirrors the
|
|
47
|
+
addon's global + story merge.
|
|
48
|
+
- All mock URLs moved to the helpers; FormEngine's duplicate types mock and
|
|
49
|
+
DpqlEditor's ad-hoc `closeAll()` removed.
|
|
50
|
+
|
|
51
|
+
### Reconciled with `fix/per-field-templates`
|
|
52
|
+
|
|
53
|
+
- That branch had already met the leak from the fixture side:
|
|
54
|
+
`createMockLspServer` reset the shared connections on create and close. The
|
|
55
|
+
project-level `beforeEach` covers the same ground plus stories that never
|
|
56
|
+
create a mock server (and the render client), so the fixture resets were
|
|
57
|
+
dropped in favour of the one mechanism.
|
|
58
|
+
- Its `query()` strips a path's leading slash and uses a `noApiPrefix` url
|
|
59
|
+
verbatim; `buildReqraftApiUrl` follows those rules, so the doubled-slash mock
|
|
60
|
+
spellings are gone.
|
|
61
|
+
- **A page-freezing render loop in the row menu** (from `a21640b`), reachable
|
|
62
|
+
only once FormEngine rendered offline: `FormEngine › Compact Expressions`
|
|
63
|
+
froze the tab and hung the whole suite with no output. The row kept ONE
|
|
64
|
+
`{key, items}` slot, and an expression's operands — separate TemplateFields
|
|
65
|
+
in the same row — published different keys into it, each overwrite
|
|
66
|
+
re-rendering the row and both operands. The same slot also kept an unmounted
|
|
67
|
+
editor's handlers when a reopened row offered the same key. Fixed in
|
|
68
|
+
`rowMenuContext.ts` (per-publisher registration via `useId`, withdrawn on
|
|
69
|
+
unmount, clicks delegated to the latest handler) and `TemplateField` (claims
|
|
70
|
+
the channel and hides it from what it renders, so operands keep their own
|
|
71
|
+
menu). Unit tests reproduce the loop and both stale-handler cases.
|
|
72
|
+
- `ExpressionField › Field Menu Stays In The Toolbar` had gone stale on that
|
|
73
|
+
branch: `a21640b` moved a row field's menu into the row's ⋮ (one menu per
|
|
74
|
+
control) after the story was written. The story now asserts that single
|
|
75
|
+
menu — the row's `.options-readfirst-more`, with no `.template-more` beside
|
|
76
|
+
it — still sits level with the toolbar.
|
|
77
|
+
|
|
78
|
+
## Not causes (checked)
|
|
79
|
+
|
|
80
|
+
- "No Preview" in failure output: addon-vitest injects Storybook's hidden preview
|
|
81
|
+
body into every test page; a failed query's DOM dump prints it.
|
|
82
|
+
- A `+` in the checkout path hangs `yarn test:stories` before any test runs
|
|
83
|
+
(mechanism not traced); unrelated to the stories.
|
|
84
|
+
|
|
85
|
+
## Follow-ups (not done)
|
|
86
|
+
|
|
87
|
+
- `users?action=current` is still unmocked for most stories — harmless today
|
|
88
|
+
(`waitForStorage={false}`), but CI renders a real user while local runs render
|
|
89
|
+
none. Candidate for a default mock once permission-gated snapshots are checked.
|
|
90
|
+
- Unmocked requests still pass through to the network. Failing them loudly for
|
|
91
|
+
non-live stories would make this class impossible rather than documented.
|
|
92
|
+
- `ReqraftWebSocketsManager.closeAll()` deletes entries by `socket.url` rather than
|
|
93
|
+
the pool key, and closing a CONNECTING socket reports code 1006, which schedules
|
|
94
|
+
a reconnect. Not exercised by this fix.
|
|
95
|
+
- ~~`tests.yml` runs only on `pull_request`~~ — done on this branch: it now also
|
|
96
|
+
runs on pushes to `develop` (the push trigger had been dropped in 2021 with no
|
|
97
|
+
recorded reason). Conflicting PRs still get no `pull_request` runs until they
|
|
98
|
+
merge up.
|
package/README.md
CHANGED
|
@@ -148,7 +148,7 @@ client.onNotification('qonsole/sessionStateChanged', (params) => { /* … */ });
|
|
|
148
148
|
client.disconnect();
|
|
149
149
|
```
|
|
150
150
|
|
|
151
|
-
Clients on the same LSP endpoint share ONE underlying WebSocket — each `ReqraftLspClient` is a per-document facade over the shared connection, multiplexed by document URI (the server keys language sessions per document), so N editors cost one socket. Auto-reconnect re-opens every document on the shared socket, 15s request timeout, request/response correlation by `id`, pending requests rejected on close. Document URIs should be opaque and client-generated — per the Qonsole LSP contract they must not contain session tokens, usernames, sandbox identifiers, or other secrets that end up in server logs.
|
|
151
|
+
Clients on the same LSP endpoint share ONE underlying WebSocket — each `ReqraftLspClient` is a per-document facade over the shared connection, multiplexed by document URI (the server keys language sessions per document), so N editors cost one socket. Auto-reconnect re-opens every document on the shared socket, 15s request timeout, request/response correlation by `id`, pending requests rejected on close. A `connect()` never outlives its socket: once the socket exhausts `maxReconnectTries`, a handshake still waiting rejects, and the next `connect()` — from that client or any other — dials again, so an editor opened after an outage connects once the server is back, without a page reload. Document URIs should be opaque and client-generated — per the Qonsole LSP contract they must not contain session tokens, usernames, sandbox identifiers, or other secrets that end up in server logs.
|
|
152
152
|
|
|
153
153
|
## Community
|
|
154
154
|
|
|
@@ -124,6 +124,116 @@ templates/return-type, and bind a provider only when the field supplies
|
|
|
124
124
|
one. Worst case, text mode still parses/serializes correctly with no
|
|
125
125
|
provider; only completions are reduced.
|
|
126
126
|
|
|
127
|
+
## Detecting an expression typed as plain text
|
|
128
|
+
|
|
129
|
+
*Added 2026-09-06. As-built.*
|
|
130
|
+
|
|
131
|
+
An author who never opens the expression view still types DPQL into the
|
|
132
|
+
ordinary editor. `TemplateField` notices, and what it does next depends on
|
|
133
|
+
the field's own type.
|
|
134
|
+
|
|
135
|
+
**A successful parse means nothing.** This is the finding the whole design
|
|
136
|
+
rests on, and it is counter-intuitive enough to be worth stating plainly.
|
|
137
|
+
Verified against the live LSP: `dpql/parse` returns `success: true` for
|
|
138
|
+
`hello`, for `42`, for `2026-09-06` and for `@a`. A bare literal is a valid
|
|
139
|
+
DPQL program, so "does it parse?" cannot separate an expression from a
|
|
140
|
+
value. What separates them is the shape of the AST that comes back:
|
|
141
|
+
|
|
142
|
+
| typed text | `exp` | verdict |
|
|
143
|
+
|---|---|---|
|
|
144
|
+
| `hello`, `42`, `2026-09-06`, `@a` | `value` | a literal |
|
|
145
|
+
| `$local:count` | `template` | a template |
|
|
146
|
+
| `@a > 5`, `"a" + "b"`, `toInt("5")`, `@n LIKE "a%"` | `>`, `+`, `toInt`, `like` | an expression |
|
|
147
|
+
|
|
148
|
+
Text that is not DPQL at all is safe on its own: `hello world`, `x@y.com`,
|
|
149
|
+
`a - b test` and `{"a":1}` all fail to parse outright.
|
|
150
|
+
|
|
151
|
+
**Three stages, in `helpers/dpqlDetection.ts`:**
|
|
152
|
+
|
|
153
|
+
1. `mightBeDpqlExpression` — a cheap lexical pass whose ONLY job is to keep
|
|
154
|
+
a server round-trip off every keystroke. It decides nothing. `-` and `/`
|
|
155
|
+
require surrounding spaces so a date or a path never triggers a probe.
|
|
156
|
+
2. `dpql/parse` on the shared probe document (below), debounced 400 ms.
|
|
157
|
+
3. `classifyTypedText` — `switch` when the text could not be a literal of
|
|
158
|
+
the field's declared type (the form's own `validateField` answers that),
|
|
159
|
+
`offer` when it could, `none` otherwise.
|
|
160
|
+
|
|
161
|
+
**Why the asymmetry.** Rewriting the string `a + b` into a concatenation on
|
|
162
|
+
a `string` field would destroy a value the author meant, so a type that
|
|
163
|
+
accepts any text is only ever OFFERED the switch. Text that could not be a
|
|
164
|
+
literal there was already an error the moment it was typed, so switching
|
|
165
|
+
costs nothing and explains the error. Every switch carries an Undo that
|
|
166
|
+
restores the exact text, and a declined text is never asked about again.
|
|
167
|
+
|
|
168
|
+
**Reachability.** The auto-switch only applies where the editor accepts free
|
|
169
|
+
text — a constrained `string` (identifier / `validation_regex`), `binary`,
|
|
170
|
+
`hash`. `int` and `float` render `input[type=number]`, which drops `@`, `>`
|
|
171
|
+
and spaces before any handler runs, so detection there is unreachable by
|
|
172
|
+
design of the editor and the ⋮ menu remains the way in. Pinned by a test.
|
|
173
|
+
|
|
174
|
+
**Template precedence.** `isValueTemplate` is deliberately loose (starts
|
|
175
|
+
with `$`, contains `:`), so `$local:count + 1` was being swallowed into
|
|
176
|
+
template mode with its arithmetic as dead text. A value that is not one
|
|
177
|
+
complete template token and carries an operator now stays in the plain
|
|
178
|
+
editor, where detection can reach it. A token standing alone
|
|
179
|
+
(`$local:count`, `$data:{1.field}`) still flips, unchanged.
|
|
180
|
+
|
|
181
|
+
**The probe document** (`components/dpqlEditor/dpqlProbe.ts`). One shared,
|
|
182
|
+
lazily-opened DPQL document for the whole app, reference-counted by
|
|
183
|
+
`useDpqlProbe` and closed when the last field using it unmounts. It is
|
|
184
|
+
cheap: `ReqraftLspClient` multiplexes every document over ONE socket per
|
|
185
|
+
endpoint and `initialize` runs once for it, so a probe is one extra
|
|
186
|
+
`didOpen` plus one server-side session — not a connection. It is still
|
|
187
|
+
shared rather than per-field, because a form with forty expression-capable
|
|
188
|
+
options would otherwise open forty sessions to ask the same question.
|
|
189
|
+
|
|
190
|
+
The document binds NO provider context; verified live, a context-less
|
|
191
|
+
`didOpen` still builds a session that `dpql/parse` answers on. It sends no
|
|
192
|
+
`target_type` either: detection asks whether the text is an expression, not
|
|
193
|
+
whether it is the right type — a mismatch is something to show the author
|
|
194
|
+
inside the editor, never a reason to refuse to open it. A probe never
|
|
195
|
+
throws; an unreachable instance simply leaves the typed text alone.
|
|
196
|
+
|
|
197
|
+
## Return-type checking
|
|
198
|
+
|
|
199
|
+
*Added 2026-09-06. As-built.*
|
|
200
|
+
|
|
201
|
+
`dpql/parse` has always been able to answer "can this expression's result
|
|
202
|
+
satisfy type X?" — it takes a `target_type` and returns `inferred_type`,
|
|
203
|
+
`type_compatible`, `auto_coercible` and a `suggested_fix`. Nothing in the
|
|
204
|
+
front end ever sent one, so it never answered.
|
|
205
|
+
|
|
206
|
+
`ExpressionField` now sends the field's own type with every parse, and
|
|
207
|
+
shows what comes back. Three outcomes, not two:
|
|
208
|
+
|
|
209
|
+
| the expression | shown |
|
|
210
|
+
|---|---|
|
|
211
|
+
| already fits | nothing |
|
|
212
|
+
| converts, and the conversion is TOTAL (a number used as text) | nothing |
|
|
213
|
+
| converts, but the conversion may FAIL (text used as a number) | a warning, with the conversion offered |
|
|
214
|
+
| cannot convert at all | a danger message, with the conversion offered |
|
|
215
|
+
|
|
216
|
+
The middle row is why the server grew `coercion_may_fail`: `canAutoCoerce()`
|
|
217
|
+
admits both kinds, and reporting a conversion that cannot fail is what
|
|
218
|
+
teaches authors to ignore the reports that matter.
|
|
219
|
+
|
|
220
|
+
`auto` and `any` are never sent as a target — they accept anything, so the
|
|
221
|
+
answer would always be "compatible" and the round trip would buy nothing. A
|
|
222
|
+
field offering a CHOICE of return types sends nothing either, rather than
|
|
223
|
+
asking about one of them arbitrarily.
|
|
224
|
+
|
|
225
|
+
**What the field cannot decide.** Whether text really denotes a number
|
|
226
|
+
depends on the text, which does not exist until the expression runs. So the
|
|
227
|
+
warning is a warning, not a refusal, and the value is checked again
|
|
228
|
+
server-side at run time — see `design/test-interface-object.md` in the qorus
|
|
229
|
+
repo. For that to be possible the FormEngine's stored envelope carries the
|
|
230
|
+
field's `type` beside `is_expression` and the AST, which is the type the
|
|
231
|
+
author was shown.
|
|
232
|
+
|
|
233
|
+
The same analysis lives in two server handlers (the LSP's `dpql/parse` and
|
|
234
|
+
the Creator WS equivalent); both were changed together. Deduplicating them
|
|
235
|
+
is a separate cleanup.
|
|
236
|
+
|
|
127
237
|
## Out of scope
|
|
128
238
|
|
|
129
239
|
- `server_expression_handling` server-function-vs-qorus-function
|
|
@@ -129,6 +129,158 @@ Create `src/components/form/fields/auto/AutoFormField.tsx`:
|
|
|
129
129
|
collapsing to `'long-string'`. **This is the one behaviour change for
|
|
130
130
|
existing consumers** — see Migration impact.
|
|
131
131
|
|
|
132
|
+
**Revised 2026-09-14 — an untyped field is typed into, never asked for a
|
|
133
|
+
type.** No field shows the type picker's *"Please select data type"*
|
|
134
|
+
anymore. It asked a question about storage ("is this Text or a Number?")
|
|
135
|
+
that an author writing a value often cannot answer, before they could write
|
|
136
|
+
anything, and it replaced a typable field with a pick-only one.
|
|
137
|
+
|
|
138
|
+
- **`AutoFormField`**, for a type that is still `auto` / `any`, renders the
|
|
139
|
+
long-string editor and stores what is typed as untyped — exactly what
|
|
140
|
+
template mode stores. The picker appears only where there is a real
|
|
141
|
+
choice: the schema allows several concrete types (`allowed_types`), or
|
|
142
|
+
the field already holds a value of a concrete type.
|
|
143
|
+
- **An explicit type** is chosen from the field's ⋮ menu — the per-type
|
|
144
|
+
entries under *Set Custom Value* (see `engine/typeChoices.ts`).
|
|
145
|
+
- **`TemplateField`** opens an empty untyped field that may hold a custom
|
|
146
|
+
value in template mode, whose editor is typable and offers the templates.
|
|
147
|
+
It decides that from the field's props, not from whether the template list
|
|
148
|
+
has arrived: on a cold load the type-filtered list does not exist at
|
|
149
|
+
mount, and a landing chosen from it put every such field on the picker.
|
|
150
|
+
- A field that may NOT hold a custom value (FormEngine passes
|
|
151
|
+
`allowCustomValues={false}` for `any`) still opens on its template menu —
|
|
152
|
+
a pick-only control because the schema made it one, not a type question.
|
|
153
|
+
- Emptying that editor leaves the field in template mode, where an empty
|
|
154
|
+
field lands. Switching to custom mode mounted a different editor in place
|
|
155
|
+
of the one being typed in, so the last backspace lost the cursor.
|
|
156
|
+
|
|
157
|
+
Guarded by `__tests__/untypedFieldNeverAsksForAType.test.tsx` and the
|
|
158
|
+
`AutoFormField` / `TemplateField` stories (`Empty`, `ViaFormEngine`,
|
|
159
|
+
`AutoComponent`, `EmptyAnyOpensOnTemplates`).
|
|
160
|
+
|
|
161
|
+
**Revised 2026-09-15 — template mode draws references as named chips.**
|
|
162
|
+
Template mode's typable editor (a string or untyped field that may also hold
|
|
163
|
+
a custom value) is `RichTextFormField` with `valueFormat: 'text'`, not a
|
|
164
|
+
textarea. The field still stores the plain string; each template reference in
|
|
165
|
+
it (`TEMPLATE_TOKEN_SOURCE`) is drawn as a chip, so a chosen template reads as
|
|
166
|
+
the name it was chosen by — in the Visual builder's operands and in every
|
|
167
|
+
string field that takes templates. A textarea spelled it `$local:name`.
|
|
168
|
+
|
|
169
|
+
- The chip's label is `templateChipLabel`: the catalogue's name for the
|
|
170
|
+
reference, else the reference as the DPQL Text view labels it
|
|
171
|
+
(`local: name`), so one reference reads alike in both views. Its hover and
|
|
172
|
+
colour are the collapsed row's (`ReadOnlyTemplateTag`).
|
|
173
|
+
- The editor keeps its own document and rebuilds it only when the stored
|
|
174
|
+
string changes from outside: rebuilding from the echo of what was typed
|
|
175
|
+
would hand the editor a new tree per keystroke, which moves the cursor.
|
|
176
|
+
- `string` holds one line: Enter adds none, and a pasted break is flattened.
|
|
177
|
+
- A value that is exactly one braced reference (`$data:{…}`, machine-written)
|
|
178
|
+
keeps its pick-only chip selector, unchanged.
|
|
179
|
+
- Only a value that STARTS with a reference enters template mode, so
|
|
180
|
+
`AutoFormField`'s text editor — `string`, `long-string` and untyped — is the
|
|
181
|
+
same chip editor whenever the field offers templates: text like
|
|
182
|
+
`Interface $local:id failed` reads with its references named too. `data`
|
|
183
|
+
and `binary` keep the textarea (encoded content), as does a field with no
|
|
184
|
+
templates to offer. Guarded by `__tests__/textFieldDrawsTemplateChips.test.tsx`
|
|
185
|
+
and the `TemplateField` stories *Template References In Text* (+ *On Phone*).
|
|
186
|
+
|
|
187
|
+
This reverses the 2026-08-27 choice (`85ba6ec`) to keep plain tokens as raw
|
|
188
|
+
text: that review rejected a *pick-only* chip because it could not be typed
|
|
189
|
+
into, and this editor is both. Conversion lives in `helpers/templateText.ts`
|
|
190
|
+
(`__tests__/templateText.test.ts`, `__tests__/richTextTextValue.test.tsx`).
|
|
191
|
+
|
|
192
|
+
**Revised 2026-09-16 — a field offers a template list only when it has one,
|
|
193
|
+
and template mode has a way out.** Two rules about the menu, both reported
|
|
194
|
+
from the stories:
|
|
195
|
+
|
|
196
|
+
- **No empty menu.** `TemplateField` hands its editor `undefined` — not an
|
|
197
|
+
empty list — when there is nothing to offer: the field's schema does not
|
|
198
|
+
allow templates (a `FormEngine` option without `supports_templates`), or the
|
|
199
|
+
type filter emptied the catalogue. An editor GIVEN a list draws the control
|
|
200
|
+
that opens it, so a list with no items opened a menu onto nothing. Guarded
|
|
201
|
+
by `__tests__/noEmptyTemplateMenu.test.tsx`.
|
|
202
|
+
- **A way back to a custom value.** Template mode's chip editor draws no `×`
|
|
203
|
+
of its own, so a field that entered template mode from the ⋮ ("Use Template")
|
|
204
|
+
offered nothing to leave it with. The ⋮ now carries "Use Custom Value"
|
|
205
|
+
whenever the field is in template mode and accepts custom values; leaving
|
|
206
|
+
clears the value only when it holds a reference (which would put the field
|
|
207
|
+
straight back into template mode) and keeps anything the author typed.
|
|
208
|
+
- **A lone group in the ⋮ opens itself.** Two of the menu's groups are
|
|
209
|
+
collapsed sections (`MenuActionsSection`, `CustomMenuItems`), so a menu
|
|
210
|
+
holding nothing but one of them asked for a click to reach the only thing on
|
|
211
|
+
offer — on an untyped field, "Set Custom Value" hiding the data types behind
|
|
212
|
+
it. It now starts expanded when it is the menu's only group; it keeps its
|
|
213
|
+
label, so the rows still say what they are, and can still be collapsed. Where
|
|
214
|
+
the menu holds more than one group the sections stay shut: there the click is
|
|
215
|
+
the choice. The same rule the template list follows for a lone category, and
|
|
216
|
+
the row menu already publishes these rows flat. Guarded by
|
|
217
|
+
`__tests__/loneMenuSectionOpensItself.test.tsx` (the section's own contract)
|
|
218
|
+
and the story *Auto · Via Form Engine Menu Opens Its Only Group* (the rule, in
|
|
219
|
+
a real browser — the menu lives in a popover jsdom never opens).
|
|
220
|
+
- **No document toolbar on a form field.** `RichTextFormField` asked Reqore
|
|
221
|
+
for undo and redo but not styling, and Reqore draws that bar as a panel as
|
|
222
|
+
wide as the tag list: an empty 600px box under the field holding two greyed
|
|
223
|
+
icons — they are disabled until there is history to walk. It is off for every
|
|
224
|
+
form use now; both still work from the keyboard, where every other text
|
|
225
|
+
field's do. The `richtext` type (the "Text" row of the data-type submenu) is
|
|
226
|
+
where this was reported. Guarded by
|
|
227
|
+
`__tests__/richTextFieldHasNoToolbar.test.tsx`.
|
|
228
|
+
|
|
229
|
+
**Revised 2026-09-16 — a field says what it takes, and an untyped one is
|
|
230
|
+
checked as the type it was given.** Two rules from the same report (picking
|
|
231
|
+
"Binary" and being told nothing about the value):
|
|
232
|
+
|
|
233
|
+
- **A binary field names its encodings.** Its placeholder reads
|
|
234
|
+
`Base64 — or 0x-prefixed hex, or a data:…;base64 URL`, which is what the
|
|
235
|
+
server actually decodes: Qorus `lib/misc.ql`
|
|
236
|
+
(`_priv_parse_ui_hash_value_intern`) reads base64 unless the value starts
|
|
237
|
+
`0x` or `data:<mime>;base64,`, symmetric with the `toBase64()` it encodes
|
|
238
|
+
with (`Classes/UserApi.qc`). Bare hex is the trap — it is not rejected, it is
|
|
239
|
+
read as base64 and corrupts. `validateField`'s `binary` branch already
|
|
240
|
+
accepted exactly these three spellings; the placeholder is that rule said
|
|
241
|
+
before the fact instead of after. A caller's own placeholder still wins, and
|
|
242
|
+
`data` is left alone — it is not base64. Guarded by
|
|
243
|
+
`__tests__/binaryFieldSaysWhatItTakes.test.tsx`.
|
|
244
|
+
- **An untyped option is validated as the type its VALUE carries.** `auto` and
|
|
245
|
+
`any` declare no type: the author picks one and it is recorded beside the
|
|
246
|
+
value. `getOptionFieldMessages` read the schema first, so a binary value was
|
|
247
|
+
validated as `auto` — which auto-detects from the value and accepts whatever
|
|
248
|
+
is there — while the form's own check prefers the stored type
|
|
249
|
+
(`getOptionFieldStorageType`). The two disagreed, so the form said "a field
|
|
250
|
+
is not valid and requires attention" while the field it meant gave no reason.
|
|
251
|
+
The messages now use the same precedence; a schema that names a concrete type
|
|
252
|
+
still wins, because the schema is what the field accepts.
|
|
253
|
+
`isUntypedOptionType` (`helpers/optionUiTypes.ts`) is the shared spelling.
|
|
254
|
+
Guarded by `__tests__/untypedFieldReportsItsChosenType.test.ts`.
|
|
255
|
+
|
|
256
|
+
**Revised 2026-09-16 (audit pass) — three rules the review pulled out of the
|
|
257
|
+
above.**
|
|
258
|
+
|
|
259
|
+
- **Whatever the field's own ⋮ offers, its ROW menu offers too.** A field
|
|
260
|
+
inside a compact row draws no menu of its own and publishes into the row's
|
|
261
|
+
(`rowMenuContext`). "Use Custom Value" was added to the drawn menu only, so
|
|
262
|
+
on the surface most options are actually edited from, template mode was still
|
|
263
|
+
a one-way door. The published list now carries it on the same condition, with
|
|
264
|
+
its own token in `publishedKey` — that key is what gates re-publication, so a
|
|
265
|
+
row without one never re-publishes when template mode flips. Guarded by
|
|
266
|
+
`__tests__/rowMenuOffersTheWayOutOfTemplateMode.test.tsx`.
|
|
267
|
+
- **`RichTextFormField` takes `tags` and does not forward it.** The editor's
|
|
268
|
+
`tags` is its template catalogue; a form field's `tags` is the chips to show.
|
|
269
|
+
Two different things under one name, and `{...rest}` sat after the computed
|
|
270
|
+
value, so a field spreading its props erased the template list — patched at
|
|
271
|
+
two call sites with `omit(rest, 'tags')` and latent at two more. `rest` is now
|
|
272
|
+
spread FIRST, `tags` is declared as the field's chips and dropped, and the
|
|
273
|
+
patches are gone.
|
|
274
|
+
- **One list of the untyped spellings.** `any`/`auto` was hand-rolled in eight
|
|
275
|
+
places. `UNTYPED_OPTION_TYPES` / `isUntypedOptionType` in
|
|
276
|
+
`helpers/optionUiTypes.ts` is now the one, and `engine/typeChoices`
|
|
277
|
+
re-exports it as `BuiltInAnyLikeTypes` for its existing callers. It lives in
|
|
278
|
+
helpers because a helper cannot import from a component.
|
|
279
|
+
|
|
280
|
+
Note that a `FormEngine` option only offers templates when it declares
|
|
281
|
+
`supports_templates` — a field with no ⋮ template entry is that option's
|
|
282
|
+
schema speaking, not a defect.
|
|
283
|
+
|
|
132
284
|
### Out of scope for phase 1
|
|
133
285
|
|
|
134
286
|
- The `type-depends-on` / `requestFieldData` cross-field type
|
|
@@ -178,7 +330,9 @@ qorus-ide coupling and copies over near-verbatim. The real work is the
|
|
|
178
330
|
in `CatalogLeafForm`. `catalogLeafToFieldSchema` already emits the
|
|
179
331
|
right shape; the adapter wires `value`/`onChange`. This is where the
|
|
180
332
|
phase-1 `auto` field pays off — leaves typed `auto` now render a
|
|
181
|
-
real type-picker instead of a textarea.
|
|
333
|
+
real type-picker instead of a textarea. (Revised 2026-09-14: an empty
|
|
334
|
+
`auto` leaf is a typable editor again, with the type on its ⋮ menu — see
|
|
335
|
+
phase 1.)
|
|
182
336
|
3. Port `CatalogNodeEditor` (group/map/list dispatch + drawer editors),
|
|
183
337
|
swapping qorus-ide's `QorusTable` for `ReqoreTable` (or a Reqraft
|
|
184
338
|
table if one exists) and `Hint` for a Reqraft equivalent or nothing.
|
|
@@ -78,13 +78,79 @@ errors: -32602 missing/invalid expression; -32803 render failure;
|
|
|
78
78
|
-32601 on servers predating the method
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
-
##
|
|
82
|
-
|
|
83
|
-
`useRenderExpression`
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
-
|
|
90
|
-
|
|
81
|
+
## Waiting, not approximating (reqraft)
|
|
82
|
+
|
|
83
|
+
`useRenderExpression()` returns `{ render, renderRich }`; both resolve the
|
|
84
|
+
server's rendering or `null`:
|
|
85
|
+
|
|
86
|
+
- A render **waits for the connection** — there is no timer racing it. The
|
|
87
|
+
connection has its own reconnect schedule and rejects once it gives up
|
|
88
|
+
(see below), so a render never outlives a dead socket.
|
|
89
|
+
- `null` means the server cannot render: the connection gave up, or the server
|
|
90
|
+
predates the method (`-32601`, remembered for the page lifetime).
|
|
91
|
+
- There is **no client-side stand-in**. A Qorus form does not work without
|
|
92
|
+
Qorus, so the approximation only ever appeared while the page's first
|
|
93
|
+
connection was still opening, marked "Approximate" on the first Explain of
|
|
94
|
+
every page. `renderExpressionToText` survives only as the synchronous summary
|
|
95
|
+
a collapsed row prints (`readFirst.ts`), and is never shown in place of a
|
|
96
|
+
server rendering.
|
|
97
|
+
|
|
98
|
+
## How an expression is shown when it is not being edited
|
|
99
|
+
|
|
100
|
+
Every read-only expression surface draws through **`DpqlRendering`**
|
|
101
|
+
(`src/components/form/expressions/DpqlRendering.tsx`): the Explain panel, the
|
|
102
|
+
Text view's Preview, the conversion a type-fit message suggests, and a collapsed
|
|
103
|
+
expression row. It is a read-only `DpqlEditor` with diagnostics and hover off,
|
|
104
|
+
so every one of them reads the same — monospace, coloured by the language
|
|
105
|
+
server's semantic tokens (the canonical tokenizer; there is no client-side
|
|
106
|
+
highlighter), template references as chips.
|
|
107
|
+
|
|
108
|
+
- `ExpressionRendering` renders an AST: it waits in the form's one waiting shape
|
|
109
|
+
(`FormFieldsSkeleton`, `data-wait="expression-rendering"`), then shows the
|
|
110
|
+
server's rendering, or says "This expression could not be rendered." when the
|
|
111
|
+
server cannot.
|
|
112
|
+
- The Preview appears only once the server's rendering exists and differs from
|
|
113
|
+
the typed text; it has no waiting state of its own.
|
|
114
|
+
- A surface with a template catalogue passes it (`templates`): a reference the
|
|
115
|
+
catalogue knows reads as the name it was chosen by, with the entry's
|
|
116
|
+
description as its hover — the Discord assistant's Save Reply row reads
|
|
117
|
+
`trim(Choices[0].message.content)`. One it does not know keeps its path
|
|
118
|
+
(`data: dc_ai_reply.choices[0].message.content`). A collapsed row passes its
|
|
119
|
+
field's own templates, else the form's; the builder's Explain passes its own.
|
|
120
|
+
- A reference's path takes every dot except one that starts a method call, so
|
|
121
|
+
the server's `$local:str.endsWith($local:p, true)` chips `$local:str`, not
|
|
122
|
+
`str.endsWith`.
|
|
123
|
+
- A new read-only expression surface uses `DpqlRendering`, never its own
|
|
124
|
+
`<code>`, rich-text field or chip splitter.
|
|
125
|
+
|
|
126
|
+
## Lifetime of the shared render socket
|
|
127
|
+
|
|
128
|
+
The module-level render client never releases its connection: the first
|
|
129
|
+
expression rendered on a page holds the endpoint's `LspSharedConnection` for
|
|
130
|
+
the rest of the page. Two consequences are designed for:
|
|
131
|
+
|
|
132
|
+
- **A socket that gives up is forgotten.** When the socket exhausts its
|
|
133
|
+
reconnect attempts, the connection fails any handshake still waiting and
|
|
134
|
+
drops the socket; the next `connect()` from any client on that endpoint
|
|
135
|
+
dials afresh. Without this, a first handshake that never completed held
|
|
136
|
+
every later editor on "Connecting to language server…" for the life of the
|
|
137
|
+
page, and one that had completed kept reporting the dead socket as ready.
|
|
138
|
+
- **Storybook resets it per story.** Stories run in one page, so the
|
|
139
|
+
connection an earlier story opened would otherwise serve a later story —
|
|
140
|
+
including one that starts its own mock LSP, which is then never dialled.
|
|
141
|
+
`.storybook/preview.tsx` runs `_resetRenderExpressionTransportForTests()`
|
|
142
|
+
and `_resetSharedLspConnectionsForTests()` in a project-level `beforeEach`.
|
|
143
|
+
- **Every story has a language server.** Because renderings wait rather than
|
|
144
|
+
approximate, the same `beforeEach` starts the mock DPQL server
|
|
145
|
+
(`dpqlMockLsp.ts`) for every story that is not `live`. Its answers follow the
|
|
146
|
+
real server's (`dpqlMockLanguage.ts`, pinned in
|
|
147
|
+
`__tests__/dpqlMockLanguage.test.ts`); a story that needs other answers starts
|
|
148
|
+
its own server on the URL, which replaces the default.
|
|
149
|
+
- **The rendering is spelled by the catalogue.** The server renders a function
|
|
150
|
+
by name (`concat("a", $local:x)`), an expression with a `render_template` by
|
|
151
|
+
that template (`$arg[0].startsWith($arg[1], $arg[2])`, a missing argument
|
|
152
|
+
read as its `default_value`), and any other operator as its arguments joined
|
|
153
|
+
by its symbol. A two-argument word comparison serializes infix
|
|
154
|
+
(`"test" startsWith "t"`) and otherwise as a call by symbol. The story server
|
|
155
|
+
reads `mockExpressions` by the same rules, which is why that fixture carries
|
|
156
|
+
the live `render_template`s and groups.
|
|
@@ -253,6 +253,27 @@ Concrete plumbing:
|
|
|
253
253
|
`SELECT * FROM users WHERE name = "Alice"` is replaced with a
|
|
254
254
|
valid DPQL expression (e.g. `1 == 1` or `2026 - 2024 == 2`).
|
|
255
255
|
|
|
256
|
+
**The server holds the text the editor shows** *(revised 2026-09-14)*. The
|
|
257
|
+
server colours and diagnoses its own copy of the document, so two things must
|
|
258
|
+
stay true, and neither did for a value set from outside rather than typed:
|
|
259
|
+
|
|
260
|
+
- **Every value reaches the server.** `SmartEditor` passes each `value` to
|
|
261
|
+
`session.didChange`, which sends only text the server does not already hold,
|
|
262
|
+
and holds text set before the document opened for `didOpen`. Before, only
|
|
263
|
+
typing was sent and `didOpen` carried the text at mount, so a Preview that
|
|
264
|
+
follows the author was coloured for text it no longer showed.
|
|
265
|
+
- **Offsets use the tree the editor holds.** Slate normalises a value set from
|
|
266
|
+
outside — a leading chip gains an empty text leaf before it — without
|
|
267
|
+
changing its text, so `value` does not change. `SmartEditor` adopts every
|
|
268
|
+
tree the editor reports as the one token, diagnostic and signature offsets
|
|
269
|
+
are computed against. Before, it kept the pre-normalisation tree and every
|
|
270
|
+
offset pointed one leaf off: a Text view seeded with
|
|
271
|
+
`"$local:name" == "John"` was never highlighted.
|
|
272
|
+
|
|
273
|
+
Guarded by `__tests__/smartEditor/sessionKeepsServerText.test.ts` and the
|
|
274
|
+
`ExpressionField` story *Via Form Engine Text Mode*, which asserts the seeded
|
|
275
|
+
text is coloured.
|
|
276
|
+
|
|
256
277
|
**Surface area.**
|
|
257
278
|
`src/utils/lspClient.ts` (legend capture, ~10 lines),
|
|
258
279
|
`src/utils/lspClient.types.ts` (new `ILspSemanticTokensLegend` /
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DpqlEditor.d.ts","sourceRoot":"","sources":["../../../src/components/dpqlEditor/DpqlEditor.tsx"],"names":[],"mappings":";AA2BA,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAG3D,YAAY,EAAE,gBAAgB,EAAE,cAAc,EAAE,CAAC;AASjD,eAAO,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"DpqlEditor.d.ts","sourceRoot":"","sources":["../../../src/components/dpqlEditor/DpqlEditor.tsx"],"names":[],"mappings":";AA2BA,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAG3D,YAAY,EAAE,gBAAgB,EAAE,cAAc,EAAE,CAAC;AASjD,eAAO,MAAM,UAAU,6GA+KtB,CAAC"}
|
|
@@ -75,7 +75,7 @@ var useDpqlSession_1 = require("./useDpqlSession");
|
|
|
75
75
|
// of completion is handled by typing inside an already-open token.
|
|
76
76
|
var DPQL_TRIGGERS = new Set(['@', '$', '.', ':']);
|
|
77
77
|
exports.DpqlEditor = (0, react_1.forwardRef)(function (_a, ref) {
|
|
78
|
-
var value = _a.value, onChange = _a.onChange, provider = _a.provider, recordType = _a.recordType, options = _a.options, actionCode = _a.actionCode, height = _a.height, _b = _a.readOnly, readOnly = _b === void 0 ? false : _b, _c = _a.showDiagnostics, showDiagnostics = _c === void 0 ? true : _c, _d = _a.enableHover, enableHover = _d === void 0 ? true : _d, _e = _a.templateTagsUseIntent, templateTagsUseIntent = _e === void 0 ? false : _e, onBlur = _a.onBlur, _f = _a.useServerParse, useServerParse = _f === void 0 ? false : _f, _g = _a.alertPayloadContext, alertPayloadContext = _g === void 0 ? false : _g, fsmContext = _a.fsmContext;
|
|
78
|
+
var value = _a.value, onChange = _a.onChange, provider = _a.provider, recordType = _a.recordType, options = _a.options, actionCode = _a.actionCode, height = _a.height, _b = _a.readOnly, readOnly = _b === void 0 ? false : _b, _c = _a.showDiagnostics, showDiagnostics = _c === void 0 ? true : _c, _d = _a.enableHover, enableHover = _d === void 0 ? true : _d, _e = _a.templateTagsUseIntent, templateTagsUseIntent = _e === void 0 ? false : _e, loadingIndicator = _a.loadingIndicator, templates = _a.templates, onBlur = _a.onBlur, _f = _a.useServerParse, useServerParse = _f === void 0 ? false : _f, _g = _a.alertPayloadContext, alertPayloadContext = _g === void 0 ? false : _g, fsmContext = _a.fsmContext;
|
|
79
79
|
var dpql = (0, useDpqlSession_1.useDpqlSession)({
|
|
80
80
|
provider: provider,
|
|
81
81
|
recordType: recordType,
|
|
@@ -180,7 +180,7 @@ exports.DpqlEditor = (0, react_1.forwardRef)(function (_a, ref) {
|
|
|
180
180
|
return dpqlHelpers_1.dpqlSlateConverter.toSlateNodes(text);
|
|
181
181
|
} });
|
|
182
182
|
}, [useServerParse, serverParsedFor, serverParsedNodes]);
|
|
183
|
-
var tagRenderer = (0, react_1.useMemo)(function () { return (0, dpqlTags_1.makeDpqlTagRenderer)(dpql.fieldMeta, { templateTagsUseIntent: templateTagsUseIntent }); }, [dpql.fieldMeta, templateTagsUseIntent]);
|
|
183
|
+
var tagRenderer = (0, react_1.useMemo)(function () { return (0, dpqlTags_1.makeDpqlTagRenderer)(dpql.fieldMeta, { templateTagsUseIntent: templateTagsUseIntent, templates: templates }); }, [dpql.fieldMeta, templateTagsUseIntent, templates]);
|
|
184
184
|
(0, react_1.useImperativeHandle)(ref, function () { return ({
|
|
185
185
|
format: function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
186
186
|
var formatted;
|
|
@@ -200,7 +200,7 @@ exports.DpqlEditor = (0, react_1.forwardRef)(function (_a, ref) {
|
|
|
200
200
|
parse: dpql.parse,
|
|
201
201
|
serialize: dpql.serialize,
|
|
202
202
|
}); }, [dpql, value, onChange]);
|
|
203
|
-
return ((0, jsx_runtime_1.jsx)(SmartEditor_1.SmartEditor, { session: dpql.session, value: value, onChange: onChange, tagRenderer: tagRenderer, triggerCharacters: DPQL_TRIGGERS, converter: converter, completionInserter: dpqlInserter_1.dpqlCompletionInserter, height: height, readOnly: readOnly, showDiagnostics: showDiagnostics, enableHover: enableHover, onBlur: onBlur, isLoading: isParsing }));
|
|
203
|
+
return ((0, jsx_runtime_1.jsx)(SmartEditor_1.SmartEditor, { session: dpql.session, value: value, onChange: onChange, tagRenderer: tagRenderer, triggerCharacters: DPQL_TRIGGERS, converter: converter, completionInserter: dpqlInserter_1.dpqlCompletionInserter, height: height, readOnly: readOnly, showDiagnostics: showDiagnostics, enableHover: enableHover, onBlur: onBlur, isLoading: isParsing, loadingIndicator: loadingIndicator }));
|
|
204
204
|
});
|
|
205
205
|
exports.DpqlEditor.displayName = 'DpqlEditor';
|
|
206
206
|
//# sourceMappingURL=DpqlEditor.js.map
|