@keboola/design 11.0.1 → 11.3.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/AGENTS.md +41 -15
- package/CHANGELOG.md +2392 -0
- package/COMPONENT-API.md +41 -2
- package/dist/{AIKit-Dre37SJr.js → AIKit-DaFT7p92.js} +23 -22
- package/dist/AIKit-DaFT7p92.js.map +1 -0
- package/dist/{Alert-DfZq9kGe.js → Alert-CseY3yAj.js} +3 -3
- package/dist/{Alert-DfZq9kGe.js.map → Alert-CseY3yAj.js.map} +1 -1
- package/dist/{AlertModal-BUC4Es8o.js → AlertModal-DQAGpsEy.js} +4 -7
- package/dist/{AlertModal-BUC4Es8o.js.map → AlertModal-DQAGpsEy.js.map} +1 -1
- package/dist/{AppShell-B5GQN6Zs.js → AppShell-BUoxM3fv.js} +29 -10
- package/dist/AppShell-BUoxM3fv.js.map +1 -0
- package/dist/{BrandEditor-B8o9zdZO.js → BrandEditor-BnTLMRMp.js} +6 -6
- package/dist/{BrandEditor-B8o9zdZO.js.map → BrandEditor-BnTLMRMp.js.map} +1 -1
- package/dist/{BrandLogo-CJkRd0F8.js → BrandLogo-V2pRUAeO.js} +2 -2
- package/dist/{BrandLogo-CJkRd0F8.js.map → BrandLogo-V2pRUAeO.js.map} +1 -1
- package/dist/{Breadcrumb-DJp7WwSv.js → Breadcrumb-CQTPn_KB.js} +3 -3
- package/dist/{Breadcrumb-DJp7WwSv.js.map → Breadcrumb-CQTPn_KB.js.map} +1 -1
- package/dist/{Button-nzmDNS2q.js → Button-CPsEQuTN.js} +16 -16
- package/dist/Button-CPsEQuTN.js.map +1 -0
- package/dist/{Card-BAoZ35CV.js → Card-Cd5HSBmv.js} +2 -2
- package/dist/{Card-BAoZ35CV.js.map → Card-Cd5HSBmv.js.map} +1 -1
- package/dist/{Checkbox-GJ8-srt4.js → Checkbox-5VNCcV7E.js} +3 -3
- package/dist/{Checkbox-GJ8-srt4.js.map → Checkbox-5VNCcV7E.js.map} +1 -1
- package/dist/{Clipboard-CBJZiviP.js → Clipboard-B7rckqV_.js} +2 -2
- package/dist/{Clipboard-CBJZiviP.js.map → Clipboard-B7rckqV_.js.map} +1 -1
- package/dist/{ClipboardButton-ez5V3fkk.js → ClipboardButton-CQ6Aewpg.js} +3 -3
- package/dist/{ClipboardButton-ez5V3fkk.js.map → ClipboardButton-CQ6Aewpg.js.map} +1 -1
- package/dist/{CodeEditor-BfQJfbhL.js → CodeEditor-CUse8znx.js} +290 -100
- package/dist/CodeEditor-CUse8znx.js.map +1 -0
- package/dist/{ColorInput-Dx8Dsv7Y.js → ColorInput-Q1D9Vcc_.js} +3 -3
- package/dist/{ColorInput-Dx8Dsv7Y.js.map → ColorInput-Q1D9Vcc_.js.map} +1 -1
- package/dist/{ColorModeSwitch-CCqj7tjE.js → ColorModeSwitch-B5PXCVqB.js} +3 -3
- package/dist/{ColorModeSwitch-CCqj7tjE.js.map → ColorModeSwitch-B5PXCVqB.js.map} +1 -1
- package/dist/{Combobox-c_xBjf0P.js → Combobox-CyoRA7oY.js} +12 -8
- package/dist/Combobox-CyoRA7oY.js.map +1 -0
- package/dist/{Command-CQ_bQsJp.js → Command-Ds68v2rX.js} +3 -3
- package/dist/{Command-CQ_bQsJp.js.map → Command-Ds68v2rX.js.map} +1 -1
- package/dist/{CopyField-BJ96zvXs.js → CopyField-DI66uY_g.js} +2 -2
- package/dist/{CopyField-BJ96zvXs.js.map → CopyField-DI66uY_g.js.map} +1 -1
- package/dist/{DateInput-CMD3dY-T.js → DateInput-BPj2pzsn.js} +4 -4
- package/dist/{DateInput-CMD3dY-T.js.map → DateInput-BPj2pzsn.js.map} +1 -1
- package/dist/{DatePicker-BbFbmsGl.js → DatePicker-DyEGuW9m.js} +2 -2
- package/dist/{DatePicker-BbFbmsGl.js.map → DatePicker-DyEGuW9m.js.map} +1 -1
- package/dist/{DateRangeInput-D3BhiKyk.js → DateRangeInput-u9DxNbHW.js} +4 -4
- package/dist/{DateRangeInput-D3BhiKyk.js.map → DateRangeInput-u9DxNbHW.js.map} +1 -1
- package/dist/{DateRangePicker-BiUgtt_M.js → DateRangePicker-CYYhX6S7.js} +6 -6
- package/dist/{DateRangePicker-BiUgtt_M.js.map → DateRangePicker-CYYhX6S7.js.map} +1 -1
- package/dist/{DropdownMenu-B6ZbYvaM.js → DropdownMenu-DpMEcyCq.js} +9 -9
- package/dist/DropdownMenu-DpMEcyCq.js.map +1 -0
- package/dist/FieldItem-qQKGU9lF.js +108 -0
- package/dist/FieldItem-qQKGU9lF.js.map +1 -0
- package/dist/FieldItem-vhIJW4pj.d.ts +103 -0
- package/dist/{FileUpload-sXRv7JiY.js → FileUpload-C336MVnU.js} +2 -2
- package/dist/{FileUpload-sXRv7JiY.js.map → FileUpload-C336MVnU.js.map} +1 -1
- package/dist/{Form-BDCef6O9.js → Form-CTygENDc.js} +21 -81
- package/dist/{Form-BDCef6O9.js.map → Form-CTygENDc.js.map} +1 -1
- package/dist/{FormGroup-S9mPNHKH.js → FormGroup-BnwP0jNu.js} +7 -7
- package/dist/FormGroup-BnwP0jNu.js.map +1 -0
- package/dist/{FullScreenModal-CJa2VkJ2.js → FullScreenModal-j-M4aPFd.js} +3 -3
- package/dist/{FullScreenModal-CJa2VkJ2.js.map → FullScreenModal-j-M4aPFd.js.map} +1 -1
- package/dist/{HoverCard-WfDkLK1s.js → HoverCard-yQq-O49c.js} +2 -2
- package/dist/{HoverCard-WfDkLK1s.js.map → HoverCard-yQq-O49c.js.map} +1 -1
- package/dist/{InputGroup-BJWsI35s.js → InputGroup-D7zlmqPB.js} +3 -3
- package/dist/{InputGroup-BJWsI35s.js.map → InputGroup-D7zlmqPB.js.map} +1 -1
- package/dist/{Kbd-CxHAo1oo.js → Kbd-D6LpR7G2.js} +2 -2
- package/dist/{Kbd-CxHAo1oo.js.map → Kbd-D6LpR7G2.js.map} +1 -1
- package/dist/{MermaidDiagram-BB06gymm.js → MermaidDiagram-JlvuGcY-.js} +6 -87
- package/dist/MermaidDiagram-JlvuGcY-.js.map +1 -0
- package/dist/{Modal-BA5Wc3sx.js → Modal-o4ATIexE.js} +3 -3
- package/dist/{Modal-BA5Wc3sx.js.map → Modal-o4ATIexE.js.map} +1 -1
- package/dist/{MultiActionButtonGroup-CiBHxsSk.js → MultiActionButtonGroup-GTeFk-L8.js} +3 -3
- package/dist/{MultiActionButtonGroup-CiBHxsSk.js.map → MultiActionButtonGroup-GTeFk-L8.js.map} +1 -1
- package/dist/{Navbar-t16usFZQ.js → Navbar-CAQs4BZz.js} +6 -3
- package/dist/Navbar-CAQs4BZz.js.map +1 -0
- package/dist/{PageToolbar-0_1OBzaZ.js → PageToolbar-bG2YtSa3.js} +4 -4
- package/dist/PageToolbar-bG2YtSa3.js.map +1 -0
- package/dist/{Pagination-CM_Rszz-.js → Pagination-BB3X7ooY.js} +2 -2
- package/dist/{Pagination-CM_Rszz-.js.map → Pagination-BB3X7ooY.js.map} +1 -1
- package/dist/{Popconfirm-BGe1jLov.js → Popconfirm-C2Ky5hJO.js} +4 -7
- package/dist/{Popconfirm-BGe1jLov.js.map → Popconfirm-C2Ky5hJO.js.map} +1 -1
- package/dist/{Popover-Ca0V6AD1.js → Popover-DsbI2HKu.js} +7 -14
- package/dist/Popover-DsbI2HKu.js.map +1 -0
- package/dist/{RadioGroup-sIveSsNa.js → RadioGroup-BMxuZEbT.js} +3 -3
- package/dist/{RadioGroup-sIveSsNa.js.map → RadioGroup-BMxuZEbT.js.map} +1 -1
- package/dist/{Search-3UiqNZRj.js → Search-DFeECt5D.js} +2 -2
- package/dist/{Search-3UiqNZRj.js.map → Search-DFeECt5D.js.map} +1 -1
- package/dist/{SearchInput-D2fcOv7E.js → SearchInput-CCpdUego.js} +3 -3
- package/dist/{SearchInput-D2fcOv7E.js.map → SearchInput-CCpdUego.js.map} +1 -1
- package/dist/{SectionNav--7bw2b6u.js → SectionNav-Bw_MVL0_.js} +4 -4
- package/dist/{SectionNav--7bw2b6u.js.map → SectionNav-Bw_MVL0_.js.map} +1 -1
- package/dist/{Select-4YX38G5h.js → Select-D6IZVvwL.js} +5 -5
- package/dist/Select-D6IZVvwL.js.map +1 -0
- package/dist/{Sheet-BQrX8-h5.js → Sheet-BIzs2K2H.js} +3 -3
- package/dist/{Sheet-BQrX8-h5.js.map → Sheet-BIzs2K2H.js.map} +1 -1
- package/dist/{Sidebar-ROaR_AqC.js → Sidebar-r1TW4g_b.js} +5 -5
- package/dist/{Sidebar-ROaR_AqC.js.map → Sidebar-r1TW4g_b.js.map} +1 -1
- package/dist/{Slider-Da_3mS5v.js → Slider-CjxyfEty.js} +3 -3
- package/dist/{Slider-Da_3mS5v.js.map → Slider-CjxyfEty.js.map} +1 -1
- package/dist/{Switch-CX2A0v50.js → Switch-BueTV03C.js} +2 -2
- package/dist/{Switch-CX2A0v50.js.map → Switch-BueTV03C.js.map} +1 -1
- package/dist/{Tabs-EAihyqCt.js → Tabs-l72-WuhK.js} +2 -2
- package/dist/{Tabs-EAihyqCt.js.map → Tabs-l72-WuhK.js.map} +1 -1
- package/dist/{TextInput-BGed-V13.js → TextInput-DhdRk8qm.js} +3 -3
- package/dist/{TextInput-BGed-V13.js.map → TextInput-DhdRk8qm.js.map} +1 -1
- package/dist/{ThemeProvider-QncUrfJn.js → ThemeProvider-DZfGdf1v.js} +5 -4
- package/dist/{ThemeProvider-QncUrfJn.js.map → ThemeProvider-DZfGdf1v.js.map} +1 -1
- package/dist/{TimePicker-B_NegL-7.js → TimePicker-B6d2rAbX.js} +2 -2
- package/dist/{TimePicker-B_NegL-7.js.map → TimePicker-B6d2rAbX.js.map} +1 -1
- package/dist/{Toast-DQSbs3oA.js → Toast-CxXUulYN.js} +2 -2
- package/dist/{Toast-DQSbs3oA.js.map → Toast-CxXUulYN.js.map} +1 -1
- package/dist/{ZoomableSvg-DG9PnAm8.js → ZoomableSvg-CNIzRHKH.js} +4 -4
- package/dist/{ZoomableSvg-DG9PnAm8.js.map → ZoomableSvg-CNIzRHKH.js.map} +1 -1
- package/dist/{context-KxxeMHbR.js → context-BrNtMc1H.js} +3 -33
- package/dist/context-BrNtMc1H.js.map +1 -0
- package/dist/defaults-CTfvj2KB.js +34 -0
- package/dist/defaults-CTfvj2KB.js.map +1 -0
- package/dist/editors.d.ts +81 -9
- package/dist/editors.js +75 -12
- package/dist/editors.js.map +1 -1
- package/dist/flint.d.ts +15 -0
- package/dist/flint.js +212 -0
- package/dist/flint.js.map +1 -0
- package/dist/index.d.ts +361 -317
- package/dist/index.js +60 -57
- package/dist/internal/blocks/AIKit.js +1 -1
- package/dist/internal/blocks/AppShell.js +2 -2
- package/dist/internal/blocks/BrandEditor.js +1 -1
- package/dist/internal/blocks/ChartPanel.js +1 -1
- package/dist/internal/blocks/ClipboardButton.js +1 -1
- package/dist/internal/blocks/ColorInput.js +1 -1
- package/dist/internal/blocks/ColorModeSwitch.js +1 -1
- package/dist/internal/blocks/Command.js +1 -1
- package/dist/internal/blocks/CopyField.js +1 -1
- package/dist/internal/blocks/DateInput.js +1 -1
- package/dist/internal/blocks/DateRangeInput.js +1 -1
- package/dist/{DiagramSkeleton-lwBS2YBa.js → internal/blocks/DiagramShared/DiagramSkeleton.js} +3 -3
- package/dist/internal/blocks/DiagramShared/DiagramSkeleton.js.map +1 -0
- package/dist/internal/blocks/EmptyConfigurationActionCard.js +1 -1
- package/dist/internal/blocks/ErrorState.js +1 -1
- package/dist/internal/blocks/ExportMenu.js +3 -3
- package/dist/internal/blocks/Form/connectors/MultiComboboxField.js +56 -0
- package/dist/internal/blocks/Form/connectors/MultiComboboxField.js.map +1 -0
- package/dist/internal/blocks/Form.js +1 -1
- package/dist/internal/blocks/FormGroup.js +1 -1
- package/dist/internal/blocks/MultiActionButtonGroup.js +1 -1
- package/dist/internal/blocks/MultiCombobox.js +10 -4
- package/dist/internal/blocks/MultiCombobox.js.map +1 -1
- package/dist/internal/blocks/NumberInput.js +1 -1
- package/dist/internal/blocks/PageToolbar.js +1 -1
- package/dist/internal/blocks/PasswordInput.js +2 -2
- package/dist/internal/blocks/SearchInput.js +1 -1
- package/dist/internal/blocks/SearchInputWithNavigation.js +3 -3
- package/dist/internal/blocks/SectionNav.js +1 -1
- package/dist/internal/blocks/SplitButton.js +2 -2
- package/dist/internal/blocks/StatCard.js +1 -1
- package/dist/internal/blocks/TextInput.js +1 -1
- package/dist/internal/blocks/Textarea.js +1 -1
- package/dist/internal/blocks/TimeInput.js +3 -3
- package/dist/internal/components/Alert.js +1 -1
- package/dist/internal/components/AlertModal.js +1 -1
- package/dist/internal/components/Avatar.js +1 -1
- package/dist/internal/components/BrandLogo.js +1 -1
- package/dist/internal/components/Breadcrumb.js +1 -1
- package/dist/internal/components/Button.js +1 -1
- package/dist/internal/components/Card.js +1 -1
- package/dist/internal/components/Checkbox.js +1 -1
- package/dist/internal/components/Clipboard.js +1 -1
- package/dist/internal/components/CollapsiblePanel.js +1 -1
- package/dist/internal/components/Combobox.js +1 -1
- package/dist/internal/components/DatePicker.js +1 -1
- package/dist/internal/components/DateRangePicker.js +1 -1
- package/dist/internal/components/DropdownMenu.js +1 -1
- package/dist/internal/components/FileUpload.js +1 -1
- package/dist/internal/components/FullScreenModal.js +1 -1
- package/dist/internal/components/HoverCard.js +1 -1
- package/dist/internal/components/InputGroup.js +1 -1
- package/dist/internal/components/Kbd.js +1 -1
- package/dist/internal/components/Modal.js +1 -1
- package/dist/internal/components/Navbar.js +1 -1
- package/dist/internal/components/Pagination.js +1 -1
- package/dist/internal/components/Popconfirm.js +1 -1
- package/dist/internal/components/Popover.js +1 -1
- package/dist/internal/components/RadioGroup.js +1 -1
- package/dist/internal/components/Search.js +1 -1
- package/dist/internal/components/Select.js +1 -1
- package/dist/internal/components/Sheet.js +1 -1
- package/dist/internal/components/Sidebar.js +1 -1
- package/dist/internal/components/Slider.js +1 -1
- package/dist/internal/components/Switch.js +1 -1
- package/dist/internal/components/Tabs.js +1 -1
- package/dist/internal/components/ThemeProvider.js +3 -2
- package/dist/internal/components/TimePicker.js +1 -1
- package/dist/internal/components/Toast.js +2 -2
- package/dist/internal/components/Tooltip.js +1 -1
- package/dist/internal/components/Truncated.js +16 -8
- package/dist/internal/components/Truncated.js.map +1 -1
- package/dist/internal/components/ZoomableSvg.js +1 -1
- package/dist/internal/utils.js +1 -1
- package/dist/markdown-editor.js +7 -7
- package/dist/mermaid.js +1 -1
- package/dist/rjsf.d.ts +13 -1
- package/dist/rjsf.js +237 -177
- package/dist/rjsf.js.map +1 -1
- package/dist/{styles-DSUP_-9Z.js → styles-BAFscjSV.js} +4 -3
- package/dist/styles-BAFscjSV.js.map +1 -0
- package/dist/styles.css +1 -1
- package/dist/svgTransforms-C9njt92h.js +89 -0
- package/dist/svgTransforms-C9njt92h.js.map +1 -0
- package/dist/testing.js +3 -2
- package/dist/testing.js.map +1 -1
- package/dist/{themeTokens-BNg98Mu9.js → themeTokens-7T1AFLhq.js} +13 -6
- package/dist/{themeTokens-BNg98Mu9.js.map → themeTokens-7T1AFLhq.js.map} +1 -1
- package/dist/{toast-CjkURw0M.js → toast-BweSoKn3.js} +3 -3
- package/dist/toast-BweSoKn3.js.map +1 -0
- package/dist/types-BPcAjMG0.d.ts +10 -0
- package/dist/{useColorSchemeState-CYqcUfSH.js → useColorSchemeState-BJEk6esG.js} +2 -2
- package/dist/{useColorSchemeState-CYqcUfSH.js.map → useColorSchemeState-BJEk6esG.js.map} +1 -1
- package/dist/{utils-D0c5VAyF.js → utils-B-g7d_Jb.js} +2 -2
- package/dist/{utils-D0c5VAyF.js.map → utils-B-g7d_Jb.js.map} +1 -1
- package/dist/vega.d.ts +46 -0
- package/dist/vega.js +26 -0
- package/dist/vega.js.map +1 -0
- package/dist/vegaTheme-FBXgAdHK.js +146 -0
- package/dist/vegaTheme-FBXgAdHK.js.map +1 -0
- package/package.json +29 -9
- package/src/styles.css +27 -4
- package/dist/AIKit-Dre37SJr.js.map +0 -1
- package/dist/AppShell-B5GQN6Zs.js.map +0 -1
- package/dist/Button-nzmDNS2q.js.map +0 -1
- package/dist/CodeEditor-BfQJfbhL.js.map +0 -1
- package/dist/Combobox-c_xBjf0P.js.map +0 -1
- package/dist/DiagramSkeleton-lwBS2YBa.js.map +0 -1
- package/dist/DropdownMenu-B6ZbYvaM.js.map +0 -1
- package/dist/FormGroup-S9mPNHKH.js.map +0 -1
- package/dist/MermaidDiagram-BB06gymm.js.map +0 -1
- package/dist/Navbar-t16usFZQ.js.map +0 -1
- package/dist/PageToolbar-0_1OBzaZ.js.map +0 -1
- package/dist/Popover-Ca0V6AD1.js.map +0 -1
- package/dist/Select-4YX38G5h.js.map +0 -1
- package/dist/constants-D6JcsD4_.d.ts +0 -41
- package/dist/context-KxxeMHbR.js.map +0 -1
- package/dist/styles-DSUP_-9Z.js.map +0 -1
- package/dist/toast-CjkURw0M.js.map +0 -1
package/dist/rjsf.js
CHANGED
|
@@ -1,111 +1,26 @@
|
|
|
1
|
-
import { Tooltip, debounce } from "./utils-
|
|
1
|
+
import { Tooltip, debounce } from "./utils-B-g7d_Jb.js";
|
|
2
2
|
import { BookOpen, Info, Trash2 } from "./icons-Cek151jC.js";
|
|
3
|
-
import { Button } from "./Button-
|
|
3
|
+
import { Button } from "./Button-CPsEQuTN.js";
|
|
4
4
|
import { Label } from "./internal/components/Label.js";
|
|
5
5
|
import { Link } from "./internal/components/Link.js";
|
|
6
|
-
import { TextInput } from "./TextInput-
|
|
7
|
-
import { RadioGroup } from "./RadioGroup-
|
|
8
|
-
import { Checkbox } from "./Checkbox-
|
|
9
|
-
import { Combobox } from "./Combobox-
|
|
10
|
-
import {
|
|
11
|
-
import { DateInput } from "./DateInput-CMD3dY-T.js";
|
|
6
|
+
import { TextInput } from "./TextInput-DhdRk8qm.js";
|
|
7
|
+
import { RadioGroup } from "./RadioGroup-BMxuZEbT.js";
|
|
8
|
+
import { Checkbox } from "./Checkbox-5VNCcV7E.js";
|
|
9
|
+
import { Combobox } from "./Combobox-CyoRA7oY.js";
|
|
10
|
+
import { FormGroup } from "./FormGroup-BnwP0jNu.js";
|
|
12
11
|
import { NumberInput } from "./internal/blocks/NumberInput.js";
|
|
12
|
+
import { Textarea } from "./internal/blocks/Textarea.js";
|
|
13
|
+
import { DateInput } from "./DateInput-BPj2pzsn.js";
|
|
13
14
|
import { PasswordInput } from "./internal/blocks/PasswordInput.js";
|
|
14
|
-
import {
|
|
15
|
-
import { Alert } from "./Alert-DfZq9kGe.js";
|
|
15
|
+
import { Alert } from "./Alert-CseY3yAj.js";
|
|
16
16
|
import { CollapsiblePanel } from "./internal/components/CollapsiblePanel.js";
|
|
17
|
-
import { Tabs, TabsContent } from "./Tabs-
|
|
18
|
-
import { CodeEditor, isLanguageMode } from "./CodeEditor-
|
|
17
|
+
import { Tabs, TabsContent } from "./Tabs-l72-WuhK.js";
|
|
18
|
+
import { CodeEditor, isLanguageMode } from "./CodeEditor-CUse8znx.js";
|
|
19
19
|
import { createContext, isValidElement, use, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
20
20
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
21
21
|
import DOMPurify from "dompurify";
|
|
22
22
|
import Form from "@rjsf/core";
|
|
23
23
|
import validator from "@rjsf/validator-ajv8";
|
|
24
|
-
//#region src/blocks/RjsfSchemaEditor/markdownContext.ts
|
|
25
|
-
/** Falls back to plain text when the host app doesn't provide a markdown renderer. */
|
|
26
|
-
const RenderMarkdownContext = createContext((source) => source);
|
|
27
|
-
const RenderMarkdownProvider = RenderMarkdownContext;
|
|
28
|
-
const useRenderMarkdown = () => use(RenderMarkdownContext);
|
|
29
|
-
//#endregion
|
|
30
|
-
//#region src/blocks/RjsfSchemaEditor/widgets/CodeEditorWidget.tsx
|
|
31
|
-
const isValidJson = (raw) => {
|
|
32
|
-
try {
|
|
33
|
-
const parsed = JSON.parse(raw);
|
|
34
|
-
return Boolean(parsed && typeof parsed === "object");
|
|
35
|
-
} catch {
|
|
36
|
-
return false;
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
const sanitize = (val) => {
|
|
40
|
-
if (typeof val === "object" && val !== null) return JSON.stringify(val, null, " ");
|
|
41
|
-
return String(val ?? "");
|
|
42
|
-
};
|
|
43
|
-
const CodeEditorWidget = ({ id, value, onChange, disabled, readonly, options }) => {
|
|
44
|
-
const editorOptions = options.editor ?? {};
|
|
45
|
-
const rawMode = editorOptions.mode ?? "application/json";
|
|
46
|
-
const mode = isLanguageMode(rawMode) ? rawMode : "application/json";
|
|
47
|
-
const isJsonMode = mode === "application/json";
|
|
48
|
-
const isReadOnly = disabled || readonly || !!editorOptions.readOnly;
|
|
49
|
-
const [text, setText] = useState(() => sanitize(value));
|
|
50
|
-
useEffect(() => {
|
|
51
|
-
setText((currentText) => {
|
|
52
|
-
const sanitized = sanitize(value);
|
|
53
|
-
if (currentText === sanitized) return currentText;
|
|
54
|
-
if (isJsonMode && isValidJson(currentText)) try {
|
|
55
|
-
if (JSON.stringify(JSON.parse(currentText)) === JSON.stringify(typeof value === "object" ? value : JSON.parse(sanitized))) return currentText;
|
|
56
|
-
} catch {}
|
|
57
|
-
return sanitized;
|
|
58
|
-
});
|
|
59
|
-
}, [value, isJsonMode]);
|
|
60
|
-
const handleChange = (raw) => {
|
|
61
|
-
setText(raw);
|
|
62
|
-
if (isJsonMode && isValidJson(raw)) onChange(JSON.parse(raw));
|
|
63
|
-
else onChange(raw);
|
|
64
|
-
};
|
|
65
|
-
const help = isJsonMode && !isReadOnly && options.encryptionHint !== false ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
66
|
-
"Properties prefixed with ",
|
|
67
|
-
/* @__PURE__ */ jsx("code", { children: "#" }),
|
|
68
|
-
" sign will be encrypted on save. Already encrypted strings will persist."
|
|
69
|
-
] }) : null;
|
|
70
|
-
return /* @__PURE__ */ jsx("div", {
|
|
71
|
-
id,
|
|
72
|
-
children: isReadOnly ? /* @__PURE__ */ jsx(CodeEditor, {
|
|
73
|
-
variant: "field",
|
|
74
|
-
value: text,
|
|
75
|
-
mode,
|
|
76
|
-
readOnly: true,
|
|
77
|
-
withCopyButton: true,
|
|
78
|
-
withLineNumbers: editorOptions.lineNumbers !== false
|
|
79
|
-
}) : /* @__PURE__ */ jsx(CodeEditor, {
|
|
80
|
-
variant: "field",
|
|
81
|
-
value: text,
|
|
82
|
-
mode,
|
|
83
|
-
onChange: handleChange,
|
|
84
|
-
withCopyButton: true,
|
|
85
|
-
withLineNumbers: editorOptions.lineNumbers !== false,
|
|
86
|
-
help
|
|
87
|
-
})
|
|
88
|
-
});
|
|
89
|
-
};
|
|
90
|
-
//#endregion
|
|
91
|
-
//#region src/blocks/RjsfSchemaEditor/fields/CodeEditorField.tsx
|
|
92
|
-
/**
|
|
93
|
-
* Field wrapper for CodeEditorWidget when used with type: "object".
|
|
94
|
-
* RJSF only applies ui:widget to primitive types, so object-typed
|
|
95
|
-
* code editors need a custom field that delegates to the widget.
|
|
96
|
-
*/
|
|
97
|
-
const CodeEditorField = ({ fieldPathId, formData, onChange, disabled, readonly, uiSchema }) => {
|
|
98
|
-
const uiOptions = uiSchema?.["ui:options"];
|
|
99
|
-
return /* @__PURE__ */ jsx(CodeEditorWidget, {
|
|
100
|
-
id: fieldPathId.$id,
|
|
101
|
-
value: formData,
|
|
102
|
-
onChange: (val) => onChange(val, fieldPathId.path),
|
|
103
|
-
disabled: !!disabled,
|
|
104
|
-
readonly: !!readonly,
|
|
105
|
-
options: uiOptions ?? {}
|
|
106
|
-
});
|
|
107
|
-
};
|
|
108
|
-
//#endregion
|
|
109
24
|
//#region src/blocks/RjsfSchemaEditor/fieldHelpers.ts
|
|
110
25
|
/** No-op function reused as onBlur/onFocus stub in custom fields. */
|
|
111
26
|
const noop = () => {};
|
|
@@ -118,6 +33,8 @@ const SCHEMA_FIELD_STUBS = {
|
|
|
118
33
|
onFocus: noop,
|
|
119
34
|
errorSchema: {}
|
|
120
35
|
};
|
|
36
|
+
/** Whether a value is a keyed namespace — an object that is neither `null` nor an array. */
|
|
37
|
+
const isRecord = (value) => !!value && typeof value === "object" && !Array.isArray(value);
|
|
121
38
|
/**
|
|
122
39
|
* Resolves a dot-path against an object (e.g. "_metadata_.table.columns").
|
|
123
40
|
*
|
|
@@ -143,17 +60,6 @@ const resolveByPath = (path, data) => {
|
|
|
143
60
|
return result;
|
|
144
61
|
};
|
|
145
62
|
/**
|
|
146
|
-
* Whether a `template-watch` field is the invisible computed-helper variant.
|
|
147
|
-
*
|
|
148
|
-
* - `template-watch` replaces `ui:widget: 'hidden'`, so `ui:options.hidden` carries the schema's
|
|
149
|
-
* `options.hidden` instead.
|
|
150
|
-
* - The field stays mounted either way; only its wrapper is hidden.
|
|
151
|
-
*/
|
|
152
|
-
const isHiddenTemplateWatch = (uiSchema) => {
|
|
153
|
-
if (uiSchema?.["ui:widget"] !== "template-watch") return false;
|
|
154
|
-
return !!uiSchema["ui:options"]?.hidden;
|
|
155
|
-
};
|
|
156
|
-
/**
|
|
157
63
|
* Extracts a property name from a simple Mustache-like template.
|
|
158
64
|
* e.g. "{{item.field_name}}" → "field_name"
|
|
159
65
|
*/
|
|
@@ -210,6 +116,122 @@ const childFieldPathId = (parentFieldPathId, ...segments) => ({
|
|
|
210
116
|
* for properties without an explicit order.
|
|
211
117
|
*/
|
|
212
118
|
const sortByPropertyOrder = (properties) => Object.entries(properties).sort(([, a], [, b]) => (a.propertyOrder ?? Number.MAX_SAFE_INTEGER) - (b.propertyOrder ?? Number.MAX_SAFE_INTEGER)).map(([key]) => key);
|
|
119
|
+
/**
|
|
120
|
+
* Whether the schema asked for this field to be hidden.
|
|
121
|
+
*
|
|
122
|
+
* - `ui:widget: 'hidden'` is what RJSF itself reads, but any widget branch in
|
|
123
|
+
* `generateUiSchema` that runs later claims the slot and erases it.
|
|
124
|
+
* - `ui:options.hidden` is the copy written last, so it survives all of them.
|
|
125
|
+
*/
|
|
126
|
+
const isHiddenField = (fieldUiSchema) => fieldUiSchema?.["ui:widget"] === "hidden" || !!fieldUiSchema?.["ui:options"]?.hidden;
|
|
127
|
+
/**
|
|
128
|
+
* Whether a schema node holds children.
|
|
129
|
+
*
|
|
130
|
+
* - `properties`, `additionalProperties`, `patternProperties` or `items` alone qualify —
|
|
131
|
+
* json-editor infers the container type from them and omits `type`.
|
|
132
|
+
* - `type` may be a union (`['object', 'null']`).
|
|
133
|
+
*/
|
|
134
|
+
const isContainerSchema = (schema) => {
|
|
135
|
+
if (!schema) return false;
|
|
136
|
+
if (schema.properties || schema.additionalProperties || schema.patternProperties) return true;
|
|
137
|
+
if (schema.items) return true;
|
|
138
|
+
if (Array.isArray(schema.type)) return schema.type.includes("object") || schema.type.includes("array");
|
|
139
|
+
return schema.type === "object" || schema.type === "array";
|
|
140
|
+
};
|
|
141
|
+
/**
|
|
142
|
+
* Whether a hidden field's whole subtree should leave the form.
|
|
143
|
+
*
|
|
144
|
+
* - Hidden containers mount nothing. RJSF recurses into objects and arrays regardless of
|
|
145
|
+
* hiddenness, so a `_metadata_` subtree costs hundreds of fields for no visible output.
|
|
146
|
+
* - Hidden leaves are kept, wrapped in `tw:hidden`: their mount-phase onChange writes the
|
|
147
|
+
* schema default that sibling `options.dependencies` resolve against.
|
|
148
|
+
*/
|
|
149
|
+
const isHiddenContainer = (fieldUiSchema, schema) => isHiddenField(fieldUiSchema) && isContainerSchema(schema);
|
|
150
|
+
//#endregion
|
|
151
|
+
//#region src/blocks/RjsfSchemaEditor/markdownContext.ts
|
|
152
|
+
/** Falls back to plain text when the host app doesn't provide a markdown renderer. */
|
|
153
|
+
const RenderMarkdownContext = createContext((source) => source);
|
|
154
|
+
const RenderMarkdownProvider = RenderMarkdownContext;
|
|
155
|
+
const useRenderMarkdown = () => use(RenderMarkdownContext);
|
|
156
|
+
//#endregion
|
|
157
|
+
//#region src/blocks/RjsfSchemaEditor/widgets/CodeEditorWidget.tsx
|
|
158
|
+
const isValidJson = (raw) => {
|
|
159
|
+
try {
|
|
160
|
+
const parsed = JSON.parse(raw);
|
|
161
|
+
return Boolean(parsed && typeof parsed === "object");
|
|
162
|
+
} catch {
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
const sanitize = (val) => {
|
|
167
|
+
if (typeof val === "object" && val !== null) return JSON.stringify(val, null, " ");
|
|
168
|
+
return String(val ?? "");
|
|
169
|
+
};
|
|
170
|
+
const CodeEditorWidget = ({ id, value, onChange, disabled, readonly, options }) => {
|
|
171
|
+
const editorOptions = options.editor ?? {};
|
|
172
|
+
const rawMode = editorOptions.mode ?? "application/json";
|
|
173
|
+
const mode = isLanguageMode(rawMode) ? rawMode : "application/json";
|
|
174
|
+
const isJsonMode = mode === "application/json";
|
|
175
|
+
const isReadOnly = disabled || readonly || !!editorOptions.readOnly;
|
|
176
|
+
const [text, setText] = useState(() => sanitize(value));
|
|
177
|
+
useEffect(() => {
|
|
178
|
+
setText((currentText) => {
|
|
179
|
+
const sanitized = sanitize(value);
|
|
180
|
+
if (currentText === sanitized) return currentText;
|
|
181
|
+
if (isJsonMode && isValidJson(currentText)) try {
|
|
182
|
+
if (JSON.stringify(JSON.parse(currentText)) === JSON.stringify(typeof value === "object" ? value : JSON.parse(sanitized))) return currentText;
|
|
183
|
+
} catch {}
|
|
184
|
+
return sanitized;
|
|
185
|
+
});
|
|
186
|
+
}, [value, isJsonMode]);
|
|
187
|
+
const handleChange = (raw) => {
|
|
188
|
+
setText(raw);
|
|
189
|
+
if (isJsonMode && isValidJson(raw)) onChange(JSON.parse(raw));
|
|
190
|
+
else onChange(raw);
|
|
191
|
+
};
|
|
192
|
+
const help = isJsonMode && !isReadOnly && options.encryptionHint !== false ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
193
|
+
"Properties prefixed with ",
|
|
194
|
+
/* @__PURE__ */ jsx("code", { children: "#" }),
|
|
195
|
+
" sign will be encrypted on save. Already encrypted strings will persist."
|
|
196
|
+
] }) : null;
|
|
197
|
+
return /* @__PURE__ */ jsx("div", {
|
|
198
|
+
id,
|
|
199
|
+
children: isReadOnly ? /* @__PURE__ */ jsx(CodeEditor, {
|
|
200
|
+
variant: "field",
|
|
201
|
+
value: text,
|
|
202
|
+
mode,
|
|
203
|
+
readOnly: true,
|
|
204
|
+
withCopyButton: true,
|
|
205
|
+
withLineNumbers: editorOptions.lineNumbers !== false
|
|
206
|
+
}) : /* @__PURE__ */ jsx(CodeEditor, {
|
|
207
|
+
variant: "field",
|
|
208
|
+
value: text,
|
|
209
|
+
mode,
|
|
210
|
+
onChange: handleChange,
|
|
211
|
+
withCopyButton: true,
|
|
212
|
+
withLineNumbers: editorOptions.lineNumbers !== false,
|
|
213
|
+
help
|
|
214
|
+
})
|
|
215
|
+
});
|
|
216
|
+
};
|
|
217
|
+
//#endregion
|
|
218
|
+
//#region src/blocks/RjsfSchemaEditor/fields/CodeEditorField.tsx
|
|
219
|
+
/**
|
|
220
|
+
* Field wrapper for CodeEditorWidget when used with type: "object".
|
|
221
|
+
* RJSF only applies ui:widget to primitive types, so object-typed
|
|
222
|
+
* code editors need a custom field that delegates to the widget.
|
|
223
|
+
*/
|
|
224
|
+
const CodeEditorField = ({ fieldPathId, formData, onChange, disabled, readonly, uiSchema }) => {
|
|
225
|
+
const uiOptions = uiSchema?.["ui:options"];
|
|
226
|
+
return /* @__PURE__ */ jsx(CodeEditorWidget, {
|
|
227
|
+
id: fieldPathId.$id,
|
|
228
|
+
value: formData,
|
|
229
|
+
onChange: (val) => onChange(val, fieldPathId.path),
|
|
230
|
+
disabled: !!disabled,
|
|
231
|
+
readonly: !!readonly,
|
|
232
|
+
options: uiOptions ?? {}
|
|
233
|
+
});
|
|
234
|
+
};
|
|
213
235
|
//#endregion
|
|
214
236
|
//#region src/blocks/RjsfSchemaEditor/SchemaDescription.tsx
|
|
215
237
|
/** Renders a schema description with sanitized HTML support (links, formatting, etc.). */
|
|
@@ -245,14 +267,15 @@ const GridObjectField = ({ schema, uiSchema = {}, formData, onChange, disabled,
|
|
|
245
267
|
const hasCollapsed = uiOptions?.collapsed !== void 0;
|
|
246
268
|
const collapsed = !!uiOptions?.collapsed;
|
|
247
269
|
const disableCollapse = !!uiOptions?.disableCollapse;
|
|
248
|
-
const
|
|
249
|
-
if (
|
|
270
|
+
const mountedKeys = sortByPropertyOrder(properties).filter((key) => !isHiddenContainer(uiSchema[key], properties[key]));
|
|
271
|
+
if (mountedKeys.length === 0) return null;
|
|
250
272
|
const gridContent = /* @__PURE__ */ jsx("div", {
|
|
251
273
|
className: "tw:grid tw:grid-cols-12 tw:gap-4 tw:[&>div:empty]:hidden",
|
|
252
|
-
children:
|
|
274
|
+
children: mountedKeys.map((key) => {
|
|
253
275
|
const gridCols = properties[key]?.options?.grid_columns ?? 12;
|
|
254
276
|
const gridBreak = !!properties[key]?.options?.grid_break;
|
|
255
277
|
return /* @__PURE__ */ jsx("div", {
|
|
278
|
+
className: isHiddenField(uiSchema[key]) ? "tw:hidden" : void 0,
|
|
256
279
|
style: { gridColumn: gridBreak ? "1 / -1" : `span ${Math.min(gridCols, 12)}` },
|
|
257
280
|
children: /* @__PURE__ */ jsx(SchemaField, {
|
|
258
281
|
name: key,
|
|
@@ -364,8 +387,9 @@ const TableArrayField = ({ schema, uiSchema = {}, formData, onChange, disabled,
|
|
|
364
387
|
const properties = itemSchema?.properties ?? {};
|
|
365
388
|
const itemUiSchema = uiSchema.items ?? {};
|
|
366
389
|
const SchemaField = getSchemaField(registry);
|
|
367
|
-
const
|
|
368
|
-
const
|
|
390
|
+
const allKeys = sortByPropertyOrder(properties);
|
|
391
|
+
const columnKeys = allKeys.filter((key) => !isHiddenField(itemUiSchema[key]));
|
|
392
|
+
const isPrimitiveItems = allKeys.length === 0 && itemSchema != null;
|
|
369
393
|
const isReadOnly = disabled || readonly;
|
|
370
394
|
const fieldPath = fieldPathId?.path ?? [];
|
|
371
395
|
const itemsRef = useRef(items);
|
|
@@ -395,7 +419,7 @@ const TableArrayField = ({ schema, uiSchema = {}, formData, onChange, disabled,
|
|
|
395
419
|
return;
|
|
396
420
|
}
|
|
397
421
|
const newItem = {};
|
|
398
|
-
for (const key of
|
|
422
|
+
for (const key of allKeys) newItem[key] = defaultValueFor(properties[key] ?? {});
|
|
399
423
|
onChange([...itemsRef.current, newItem], fieldPath);
|
|
400
424
|
};
|
|
401
425
|
const withHiddenLabel = (base) => ({
|
|
@@ -411,7 +435,7 @@ const TableArrayField = ({ schema, uiSchema = {}, formData, onChange, disabled,
|
|
|
411
435
|
children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [isPrimitiveItems ? /* @__PURE__ */ jsx("th", {
|
|
412
436
|
className: "tw:border-b tw:border-neutral-200 tw:p-2 tw:text-left tw:text-xs tw:font-medium tw:text-neutral-600",
|
|
413
437
|
children: itemSchema?.title ?? ""
|
|
414
|
-
}) :
|
|
438
|
+
}) : columnKeys.map((key) => /* @__PURE__ */ jsx("th", {
|
|
415
439
|
className: "tw:border-b tw:border-neutral-200 tw:p-2 tw:text-left tw:text-xs tw:font-medium tw:text-neutral-600",
|
|
416
440
|
children: properties[key]?.title ?? key
|
|
417
441
|
}, key)), !isReadOnly && /* @__PURE__ */ jsx("th", { className: "tw:w-20" })] }) }), /* @__PURE__ */ jsx("tbody", { children: items.map((item, rowIndex) => /* @__PURE__ */ jsxs("tr", {
|
|
@@ -430,7 +454,7 @@ const TableArrayField = ({ schema, uiSchema = {}, formData, onChange, disabled,
|
|
|
430
454
|
disabled: !!disabled,
|
|
431
455
|
readonly: !!readonly
|
|
432
456
|
})
|
|
433
|
-
}) :
|
|
457
|
+
}) : columnKeys.map((key) => /* @__PURE__ */ jsx("td", {
|
|
434
458
|
className: "tw:px-2 tw:py-1.5 tw:[&>div]:mb-0",
|
|
435
459
|
children: /* @__PURE__ */ jsx(SchemaField, {
|
|
436
460
|
name: key,
|
|
@@ -507,13 +531,27 @@ const TabsObjectField = ({ schema, uiSchema = {}, formData, onChange, disabled,
|
|
|
507
531
|
[key]: value
|
|
508
532
|
}, path, errorSchema, id);
|
|
509
533
|
}, [onChange]);
|
|
510
|
-
const
|
|
511
|
-
const
|
|
512
|
-
|
|
513
|
-
const
|
|
534
|
+
const mountedKeys = sortByPropertyOrder(properties).filter((key) => !isHiddenContainer(uiSchema[key], properties[key]));
|
|
535
|
+
const tabKeys = mountedKeys.filter((key) => !isHiddenField(uiSchema[key]));
|
|
536
|
+
const hiddenLeafKeys = mountedKeys.filter((key) => isHiddenField(uiSchema[key]));
|
|
537
|
+
const [activeTab, setActiveTab] = useState(tabKeys[0] ?? "");
|
|
538
|
+
if (mountedKeys.length === 0) return null;
|
|
539
|
+
const triggers = tabKeys.map((key) => ({
|
|
514
540
|
value: key,
|
|
515
541
|
title: properties[key]?.title ?? key
|
|
516
542
|
}));
|
|
543
|
+
const renderField = (key) => /* @__PURE__ */ jsx(SchemaField, {
|
|
544
|
+
name: key,
|
|
545
|
+
schema: schema.properties[key],
|
|
546
|
+
uiSchema: uiSchema[key] ?? {},
|
|
547
|
+
formData: data[key],
|
|
548
|
+
...SCHEMA_FIELD_STUBS,
|
|
549
|
+
fieldPathId: childFieldPathId(fieldPathId, key),
|
|
550
|
+
registry,
|
|
551
|
+
onChange: onPropertyChange(key),
|
|
552
|
+
disabled: !!disabled,
|
|
553
|
+
readonly: !!readonly
|
|
554
|
+
}, key);
|
|
517
555
|
return /* @__PURE__ */ jsxs("div", {
|
|
518
556
|
className: "tw:flex tw:flex-col tw:gap-4",
|
|
519
557
|
children: [
|
|
@@ -522,27 +560,17 @@ const TabsObjectField = ({ schema, uiSchema = {}, formData, onChange, disabled,
|
|
|
522
560
|
children: schema.title
|
|
523
561
|
}),
|
|
524
562
|
/* @__PURE__ */ jsx(SchemaDescription, { description: schema.description }),
|
|
525
|
-
/* @__PURE__ */ jsx(Tabs, {
|
|
563
|
+
tabKeys.length > 0 && /* @__PURE__ */ jsx(Tabs, {
|
|
526
564
|
triggers,
|
|
527
565
|
value: activeTab,
|
|
528
566
|
onValueChange: setActiveTab,
|
|
529
567
|
compact: true,
|
|
530
|
-
children:
|
|
568
|
+
children: tabKeys.map((key) => /* @__PURE__ */ jsx(TabsContent, {
|
|
531
569
|
value: key,
|
|
532
|
-
children:
|
|
533
|
-
name: key,
|
|
534
|
-
schema: schema.properties[key],
|
|
535
|
-
uiSchema: uiSchema[key] ?? {},
|
|
536
|
-
formData: data[key],
|
|
537
|
-
...SCHEMA_FIELD_STUBS,
|
|
538
|
-
fieldPathId: childFieldPathId(fieldPathId, key),
|
|
539
|
-
registry,
|
|
540
|
-
onChange: onPropertyChange(key),
|
|
541
|
-
disabled: !!disabled,
|
|
542
|
-
readonly: !!readonly
|
|
543
|
-
})
|
|
570
|
+
children: renderField(key)
|
|
544
571
|
}, key))
|
|
545
|
-
})
|
|
572
|
+
}),
|
|
573
|
+
hiddenLeafKeys.map(renderField)
|
|
546
574
|
]
|
|
547
575
|
});
|
|
548
576
|
};
|
|
@@ -654,9 +682,13 @@ const ErrorListTemplate = ({ errors }) => {
|
|
|
654
682
|
};
|
|
655
683
|
//#endregion
|
|
656
684
|
//#region src/blocks/RjsfSchemaEditor/RootFormDataContext.ts
|
|
657
|
-
const RootFormDataContext = createContext({
|
|
685
|
+
const RootFormDataContext = createContext({
|
|
686
|
+
data: {},
|
|
687
|
+
context: {}
|
|
688
|
+
});
|
|
658
689
|
const RootFormDataProvider = RootFormDataContext;
|
|
659
|
-
const useRootFormData = () => use(RootFormDataContext);
|
|
690
|
+
const useRootFormData = () => use(RootFormDataContext).data;
|
|
691
|
+
const useRootContext = () => use(RootFormDataContext).context;
|
|
660
692
|
//#endregion
|
|
661
693
|
//#region src/blocks/RjsfSchemaEditor/templates/FieldTemplate.tsx
|
|
662
694
|
/**
|
|
@@ -776,16 +808,11 @@ const FieldTemplateWithDependencies = ({ dependencies, keepMounted, ...props })
|
|
|
776
808
|
return /* @__PURE__ */ jsx(FieldTemplateBody, { ...props });
|
|
777
809
|
};
|
|
778
810
|
const FieldTemplate = (props) => {
|
|
779
|
-
if (props.
|
|
811
|
+
if (isHiddenField(props.uiSchema)) return /* @__PURE__ */ jsx("div", {
|
|
780
812
|
className: "tw:hidden",
|
|
781
813
|
children: props.children
|
|
782
814
|
});
|
|
783
|
-
const
|
|
784
|
-
if (isHiddenTemplateWatch(props.uiSchema)) return /* @__PURE__ */ jsx("div", {
|
|
785
|
-
className: "tw:hidden",
|
|
786
|
-
children: props.children
|
|
787
|
-
});
|
|
788
|
-
const dependencies = uiOptions?.dependencies;
|
|
815
|
+
const dependencies = (props.uiSchema?.["ui:options"])?.dependencies;
|
|
789
816
|
if (dependencies) return /* @__PURE__ */ jsx(FieldTemplateWithDependencies, {
|
|
790
817
|
dependencies,
|
|
791
818
|
keepMounted: props.uiSchema?.["ui:widget"] === "template-watch",
|
|
@@ -803,22 +830,9 @@ const ObjectFieldTemplate = ({ title, description, properties, formData, uiSchem
|
|
|
803
830
|
const disableCollapse = !!uiOptions?.disableCollapse;
|
|
804
831
|
const isArrayItem = typeof fieldPathId?.path?.at(-1) === "number";
|
|
805
832
|
const childSchemas = schema.properties;
|
|
806
|
-
const
|
|
807
|
-
if (!s) return false;
|
|
808
|
-
if (s.properties || s.items) return true;
|
|
809
|
-
if (Array.isArray(s.type)) return s.type.includes("object") || s.type.includes("array");
|
|
810
|
-
return s.type === "object" || s.type === "array";
|
|
811
|
-
};
|
|
812
|
-
const visibleProperties = properties.filter((prop) => {
|
|
813
|
-
if (uiSchema?.[prop.name]?.["ui:widget"] !== "hidden") return true;
|
|
814
|
-
return !isContainerSchema(childSchemas?.[prop.name]);
|
|
815
|
-
});
|
|
816
|
-
const isHiddenMount = (name) => {
|
|
817
|
-
const childUi = uiSchema?.[name];
|
|
818
|
-
return childUi?.["ui:widget"] === "hidden" || isHiddenTemplateWatch(childUi);
|
|
819
|
-
};
|
|
833
|
+
const visibleProperties = properties.filter((prop) => !isHiddenContainer(uiSchema?.[prop.name], childSchemas?.[prop.name]));
|
|
820
834
|
const renderChildren = (props) => props.map((prop) => /* @__PURE__ */ jsx("div", {
|
|
821
|
-
className:
|
|
835
|
+
className: isHiddenField(uiSchema?.[prop.name]) ? "tw:hidden" : void 0,
|
|
822
836
|
children: prop.content
|
|
823
837
|
}, prop.name));
|
|
824
838
|
if (isRoot) return /* @__PURE__ */ jsx("div", {
|
|
@@ -1029,24 +1043,62 @@ const resolveTemplate = (template, watch, rootFormData) => {
|
|
|
1029
1043
|
});
|
|
1030
1044
|
};
|
|
1031
1045
|
/**
|
|
1046
|
+
* Whether `rootContext` declares the value a path reads.
|
|
1047
|
+
*
|
|
1048
|
+
* - A context entry shares its top-level key with the form data — a sync action writes its own
|
|
1049
|
+
* keys under the same key — so the entry key alone does not settle it.
|
|
1050
|
+
* - Both the entry and the segment under it must be own properties — plain-object lookups also
|
|
1051
|
+
* answer for `toString` and the rest of the prototype chain.
|
|
1052
|
+
* - A path naming an entry and nothing under it reads the whole namespace, context included.
|
|
1053
|
+
*/
|
|
1054
|
+
const declaresPath = (segments, rootContext) => {
|
|
1055
|
+
const [entryKey = "", key] = segments;
|
|
1056
|
+
const entry = rootContext[entryKey];
|
|
1057
|
+
return isRecord(entry) && (key === void 0 || Object.hasOwn(entry, key));
|
|
1058
|
+
};
|
|
1059
|
+
/**
|
|
1060
|
+
* Whether every watched path reads a value `rootContext` declares.
|
|
1061
|
+
*
|
|
1062
|
+
* - No watched paths means nothing is derived, which is not a context view.
|
|
1063
|
+
*/
|
|
1064
|
+
const readsOnlyContext = (watch, rootContext) => {
|
|
1065
|
+
const paths = Object.values(watch);
|
|
1066
|
+
return paths.length > 0 && paths.every((path) => {
|
|
1067
|
+
const segments = path.split(".");
|
|
1068
|
+
return declaresPath(segments, rootContext) || declaresPath(segments.slice(1), rootContext);
|
|
1069
|
+
});
|
|
1070
|
+
};
|
|
1071
|
+
/**
|
|
1032
1072
|
* Widget for json-editor's `template`/`watch` pattern (without `enumSource`).
|
|
1033
|
-
* Computes a value from watched
|
|
1073
|
+
* Computes a value from watched paths and shows it.
|
|
1034
1074
|
*
|
|
1035
1075
|
* - With `options.hidden` it renders nothing — a helper for cross-object dependencies.
|
|
1036
1076
|
* - Without it, the value is shown in a read-only input; `FieldTemplate` supplies the label.
|
|
1077
|
+
* - It writes the computed value into the form data, so a component reads it back from the
|
|
1078
|
+
* saved configuration.
|
|
1079
|
+
* - It stops writing when every watched path reads `rootContext` — the configuration does not
|
|
1080
|
+
* own that context.
|
|
1081
|
+
* - `options.hidden` fields always write; they exist to feed cross-object dependencies.
|
|
1037
1082
|
*/
|
|
1038
1083
|
const TemplateWatchWidget = ({ id, value, onChange, disabled, readonly, rawErrors, options: widgetOptions }) => {
|
|
1039
1084
|
const data = useRootFormData();
|
|
1085
|
+
const rootContext = useRootContext();
|
|
1040
1086
|
const watch = widgetOptions.watch;
|
|
1041
1087
|
const template = widgetOptions.template;
|
|
1088
|
+
const isContextView = !widgetOptions.hidden && !!watch && readsOnlyContext(watch, rootContext);
|
|
1042
1089
|
const computed = watch && template ? resolveTemplate(template, watch, data) : stringify(value);
|
|
1043
1090
|
const lastSetRef = useRef(stringify(value));
|
|
1044
1091
|
useEffect(() => {
|
|
1092
|
+
if (isContextView) return;
|
|
1045
1093
|
if (computed !== lastSetRef.current) {
|
|
1046
1094
|
lastSetRef.current = computed;
|
|
1047
1095
|
onChange(computed);
|
|
1048
1096
|
}
|
|
1049
|
-
}, [
|
|
1097
|
+
}, [
|
|
1098
|
+
computed,
|
|
1099
|
+
onChange,
|
|
1100
|
+
isContextView
|
|
1101
|
+
]);
|
|
1050
1102
|
if (widgetOptions.hidden) return null;
|
|
1051
1103
|
return /* @__PURE__ */ jsx(TextInput, {
|
|
1052
1104
|
id,
|
|
@@ -1167,7 +1219,8 @@ const generateUiSchema = (schema, readOnly = false, definitions, globalConfig, h
|
|
|
1167
1219
|
const type = propSchema.type ?? (propSchema.properties ? "object" : void 0);
|
|
1168
1220
|
const options = propSchema.options;
|
|
1169
1221
|
const fieldUi = {};
|
|
1170
|
-
|
|
1222
|
+
const isHidden = !!options?.hidden;
|
|
1223
|
+
if (isHidden) fieldUi["ui:widget"] = "hidden";
|
|
1171
1224
|
if (type === "array" && format === "table") fieldUi["ui:field"] = "tableArray";
|
|
1172
1225
|
if (type === "array" && format === "checkbox") fieldUi["ui:widget"] = "checkboxes";
|
|
1173
1226
|
if (format === "radio" && propSchema.enum) fieldUi["ui:widget"] = "radio";
|
|
@@ -1241,7 +1294,7 @@ const generateUiSchema = (schema, readOnly = false, definitions, globalConfig, h
|
|
|
1241
1294
|
...fieldUi["ui:options"],
|
|
1242
1295
|
watch: propSchema.watch,
|
|
1243
1296
|
template: propSchema.template,
|
|
1244
|
-
hidden:
|
|
1297
|
+
...isContainerSchema(propSchema) && { hidden: true }
|
|
1245
1298
|
};
|
|
1246
1299
|
}
|
|
1247
1300
|
if (type === "boolean" && options?.enum_titles) fieldUi["ui:widget"] = "select";
|
|
@@ -1297,6 +1350,10 @@ const generateUiSchema = (schema, readOnly = false, definitions, globalConfig, h
|
|
|
1297
1350
|
if (Object.keys(itemsUi).length > 0) fieldUi.items = itemsUi;
|
|
1298
1351
|
}
|
|
1299
1352
|
if ((propSchema.enumSource || propSchema.watch) && !fieldUi["ui:widget"]) console.warn(`[RJSF] Property "${key}" uses enumSource/watch which is not yet supported. It will render as a plain input.`);
|
|
1353
|
+
if (isHidden) fieldUi["ui:options"] = {
|
|
1354
|
+
...fieldUi["ui:options"],
|
|
1355
|
+
hidden: true
|
|
1356
|
+
};
|
|
1300
1357
|
if (Object.keys(fieldUi).length > 0) uiSchema[key] = fieldUi;
|
|
1301
1358
|
}
|
|
1302
1359
|
const orderedEntries = Object.entries(properties).filter(([, prop]) => prop.propertyOrder !== void 0).sort(([, a], [, b]) => (a.propertyOrder ?? Number.MAX_SAFE_INTEGER) - (b.propertyOrder ?? Number.MAX_SAFE_INTEGER));
|
|
@@ -1332,18 +1389,6 @@ const isDynamicSelectSchema = (schema) => {
|
|
|
1332
1389
|
const isTemplateWatchSchema = (schema) => {
|
|
1333
1390
|
return !!(schema.template && schema.watch && !schema.enumSource);
|
|
1334
1391
|
};
|
|
1335
|
-
/**
|
|
1336
|
-
* Whether a schema describes an object or an array.
|
|
1337
|
-
*
|
|
1338
|
-
* - `properties` or `items` imply the type even when json-editor omits it.
|
|
1339
|
-
* - `type` may be a union, e.g. `['object', 'null']`.
|
|
1340
|
-
*/
|
|
1341
|
-
const isContainerType = (schema) => {
|
|
1342
|
-
if (schema.properties || schema.items) return true;
|
|
1343
|
-
const { type } = schema;
|
|
1344
|
-
if (Array.isArray(type)) return type.includes("object") || type.includes("array");
|
|
1345
|
-
return type === "object" || type === "array";
|
|
1346
|
-
};
|
|
1347
1392
|
const isAsyncSelectSchema = (schema) => {
|
|
1348
1393
|
return !!(schema.options?.async || schema.options?.creatable);
|
|
1349
1394
|
};
|
|
@@ -1468,7 +1513,7 @@ const stableStringify = (obj) => JSON.stringify(obj, (_key, val) => {
|
|
|
1468
1513
|
}
|
|
1469
1514
|
return val;
|
|
1470
1515
|
});
|
|
1471
|
-
const RjsfSchemaEditor = ({ schema, value, onChange, readOnly, inForm, globalConfig, onRegisterValidate, widgets, fields, renderMarkdown, hasProtectedDefaultBranch = false }) => {
|
|
1516
|
+
const RjsfSchemaEditor = ({ schema, value, onChange, readOnly, inForm, globalConfig, rootContext, onRegisterValidate, widgets, fields, renderMarkdown, hasProtectedDefaultBranch = false }) => {
|
|
1472
1517
|
const schemaJs = useMemo(() => sanitizeSchema(schema), [schema]);
|
|
1473
1518
|
const uiSchema = useMemo(() => generateUiSchema(schema, readOnly, void 0, globalConfig ?? void 0, hasProtectedDefaultBranch), [
|
|
1474
1519
|
schema,
|
|
@@ -1564,12 +1609,27 @@ const RjsfSchemaEditor = ({ schema, value, onChange, readOnly, inForm, globalCon
|
|
|
1564
1609
|
return formRef.current?.validateForm() ?? true;
|
|
1565
1610
|
});
|
|
1566
1611
|
}, [onRegisterValidate, formKey]);
|
|
1612
|
+
const rootFormDataValue = useMemo(() => {
|
|
1613
|
+
const context = rootContext ?? {};
|
|
1614
|
+
const merged = { ...rootFormData };
|
|
1615
|
+
for (const [key, entry] of Object.entries(context)) {
|
|
1616
|
+
const existing = merged[key];
|
|
1617
|
+
merged[key] = isRecord(existing) ? {
|
|
1618
|
+
...existing,
|
|
1619
|
+
...entry
|
|
1620
|
+
} : entry;
|
|
1621
|
+
}
|
|
1622
|
+
return {
|
|
1623
|
+
data: merged,
|
|
1624
|
+
context
|
|
1625
|
+
};
|
|
1626
|
+
}, [rootFormData, rootContext]);
|
|
1567
1627
|
return /* @__PURE__ */ jsx("div", {
|
|
1568
1628
|
className: "json-editor",
|
|
1569
1629
|
children: /* @__PURE__ */ jsx(RenderMarkdownProvider, {
|
|
1570
1630
|
value: renderMarkdown ?? defaultRenderMarkdown,
|
|
1571
1631
|
children: /* @__PURE__ */ jsx(RootFormDataProvider, {
|
|
1572
|
-
value:
|
|
1632
|
+
value: rootFormDataValue,
|
|
1573
1633
|
children: /* @__PURE__ */ jsx(Form, {
|
|
1574
1634
|
ref: formRef,
|
|
1575
1635
|
schema: schemaJs,
|