@open-pioneer/feature-editing 1.4.0-dev.20260625074633 → 1.4.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/CHANGELOG.md +8 -2
- package/README.md +1 -3
- package/api/editor/context.js.map +1 -1
- package/api/editor/editor.d.ts +2 -2
- package/api/editor/editor.js.map +1 -1
- package/api/model/InteractionOptions.d.ts +1 -1
- package/implementation/FeatureEditor.js.map +1 -1
- package/implementation/components/action-selector/ActionSelector.js.map +1 -1
- package/implementation/components/action-selector/DrawingControls.js.map +1 -1
- package/implementation/components/action-selector/SelectButton.js.map +1 -1
- package/implementation/components/action-selector/TemplateItem.js.map +1 -1
- package/implementation/components/action-selector/TemplateSelector.js.map +1 -1
- package/implementation/components/controls/ColorPickerControl.js +1 -1
- package/implementation/components/controls/ColorPickerControl.js.map +1 -1
- package/implementation/components/controls/ComboBoxControl.js.map +1 -1
- package/implementation/components/controls/DefaultControl.js +1 -1
- package/implementation/components/controls/DefaultControl.js.map +1 -1
- package/implementation/components/controls/NumberFieldControl.js.map +1 -1
- package/implementation/components/controls/RadioGroupControl.js.map +1 -1
- package/implementation/components/controls/SelectControl.js.map +1 -1
- package/implementation/components/controls/option-hooks.js.map +1 -1
- package/implementation/components/property-editor/ButtonRow.js +1 -1
- package/implementation/components/property-editor/ButtonRow.js.map +1 -1
- package/implementation/components/property-editor/CancelConfirmationDialog.js.map +1 -1
- package/implementation/components/property-editor/DeleteConfirmationDialog.js.map +1 -1
- package/implementation/components/property-editor/PropertyEditor.js +6 -3
- package/implementation/components/property-editor/PropertyEditor.js.map +1 -1
- package/implementation/components/property-editor/PropertyField.js.map +1 -1
- package/implementation/components/property-editor/PropertyForm.js +1 -1
- package/implementation/components/property-editor/PropertyForm.js.map +1 -1
- package/implementation/context/PropertyFormContext.d.ts +0 -1
- package/implementation/context/PropertyFormContext.js +2 -2
- package/implementation/context/PropertyFormContext.js.map +1 -1
- package/implementation/context/usePropertyFormContext.js.map +1 -1
- package/implementation/editor/editorHooks.d.ts +1 -1
- package/implementation/editor/editorHooks.js +1 -1
- package/implementation/editor/editorHooks.js.map +1 -1
- package/implementation/editor/useEditingCallbacks.d.ts +1 -1
- package/implementation/editor/useEditingCallbacks.js +1 -1
- package/implementation/editor/useEditingCallbacks.js.map +1 -1
- package/implementation/geometry-editing/controller/DrawingSession.d.ts +1 -6
- package/implementation/geometry-editing/controller/DrawingSession.js +33 -33
- package/implementation/geometry-editing/controller/DrawingSession.js.map +1 -1
- package/implementation/geometry-editing/controller/EditingController.d.ts +3 -9
- package/implementation/geometry-editing/controller/EditingController.js +40 -40
- package/implementation/geometry-editing/controller/EditingController.js.map +1 -1
- package/implementation/geometry-editing/controller/UndoManager.d.ts +1 -4
- package/implementation/geometry-editing/controller/UndoManager.js +14 -14
- package/implementation/geometry-editing/controller/UndoManager.js.map +1 -1
- package/implementation/geometry-editing/controller/geometryState.js.map +1 -1
- package/implementation/geometry-editing/interactions/BaseInteraction.d.ts +1 -3
- package/implementation/geometry-editing/interactions/BaseInteraction.js +12 -12
- package/implementation/geometry-editing/interactions/BaseInteraction.js.map +1 -1
- package/implementation/geometry-editing/interactions/DoubleClickInteraction.d.ts +1 -1
- package/implementation/geometry-editing/interactions/DoubleClickInteraction.js +2 -2
- package/implementation/geometry-editing/interactions/DoubleClickInteraction.js.map +1 -1
- package/implementation/geometry-editing/interactions/DrawingInteraction.d.ts +5 -7
- package/implementation/geometry-editing/interactions/DrawingInteraction.js +13 -13
- package/implementation/geometry-editing/interactions/DrawingInteraction.js.map +1 -1
- package/implementation/geometry-editing/interactions/HighlightingInteraction.d.ts +1 -2
- package/implementation/geometry-editing/interactions/HighlightingInteraction.js +4 -4
- package/implementation/geometry-editing/interactions/HighlightingInteraction.js.map +1 -1
- package/implementation/geometry-editing/interactions/KeyboardInteraction.d.ts +2 -6
- package/implementation/geometry-editing/interactions/KeyboardInteraction.js +10 -10
- package/implementation/geometry-editing/interactions/KeyboardInteraction.js.map +1 -1
- package/implementation/geometry-editing/interactions/ModificationInteraction.d.ts +2 -3
- package/implementation/geometry-editing/interactions/ModificationInteraction.js +4 -4
- package/implementation/geometry-editing/interactions/ModificationInteraction.js.map +1 -1
- package/implementation/geometry-editing/interactions/SelectionInteraction.d.ts +3 -7
- package/implementation/geometry-editing/interactions/SelectionInteraction.js +11 -11
- package/implementation/geometry-editing/interactions/SelectionInteraction.js.map +1 -1
- package/implementation/geometry-editing/interactions/SnappingInteraction.d.ts +1 -1
- package/implementation/geometry-editing/interactions/SnappingInteraction.js.map +1 -1
- package/implementation/geometry-editing/useGeometryEditing.d.ts +1 -1
- package/implementation/geometry-editing/useGeometryEditing.js.map +1 -1
- package/package.json +12 -12
|
@@ -3,13 +3,13 @@ import { Flex, useDisclosure } from '@chakra-ui/react';
|
|
|
3
3
|
import { useEvent } from '@open-pioneer/react-utils';
|
|
4
4
|
import { useReactiveSnapshot } from '@open-pioneer/reactivity';
|
|
5
5
|
import { useMemo, useCallback } from 'react';
|
|
6
|
+
import { DeclarativeFormContext, CustomFormContextImpl, FormContext } from '../../context/PropertyFormContext.js';
|
|
7
|
+
import { usePropertyFormContext } from '../../context/usePropertyFormContext.js';
|
|
6
8
|
import { ButtonRow } from './ButtonRow.js';
|
|
7
9
|
import { CancelConfirmationDialog } from './CancelConfirmationDialog.js';
|
|
8
10
|
import { DeleteConfirmationDialog } from './DeleteConfirmationDialog.js';
|
|
9
|
-
import { DeclarativeFormContext, CustomFormContextImpl, FormContext } from '../../context/PropertyFormContext.js';
|
|
10
11
|
import { PropertyField } from './PropertyField.js';
|
|
11
12
|
import { PropertyForm } from './PropertyForm.js';
|
|
12
|
-
import { usePropertyFormContext } from '../../context/usePropertyFormContext.js';
|
|
13
13
|
|
|
14
14
|
function PropertyEditor(props) {
|
|
15
15
|
const { editingStep, callbacks, templates, resolveFormTemplate } = props;
|
|
@@ -32,7 +32,10 @@ function PropertyEditor(props) {
|
|
|
32
32
|
height: "full",
|
|
33
33
|
overflowY: "hidden",
|
|
34
34
|
children: [
|
|
35
|
-
/* @__PURE__ */ jsx(PropertyForm, { children: formTemplate.kind === "dynamic" ? formTemplate.renderForm() : formTemplate.fields.map((field, index) =>
|
|
35
|
+
/* @__PURE__ */ jsx(PropertyForm, { children: formTemplate.kind === "dynamic" ? formTemplate.renderForm() : formTemplate.fields.map((field, index) => (
|
|
36
|
+
// oxlint-disable-next-line react/no-array-index-key
|
|
37
|
+
/* @__PURE__ */ jsx(PropertyField, { field }, index)
|
|
38
|
+
)) }),
|
|
36
39
|
/* @__PURE__ */ jsx(EditorControls, {})
|
|
37
40
|
]
|
|
38
41
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PropertyEditor.js","sources":["PropertyEditor.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { Flex, useDisclosure } from \"@chakra-ui/react\";\nimport { useEvent } from \"@open-pioneer/react-utils\";\nimport { useReactiveSnapshot } from \"@open-pioneer/reactivity\";\nimport { useCallback, useMemo, type ReactElement } from \"react\";\nimport {
|
|
1
|
+
{"version":3,"file":"PropertyEditor.js","sources":["PropertyEditor.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { Flex, useDisclosure } from \"@chakra-ui/react\";\nimport { useEvent } from \"@open-pioneer/react-utils\";\nimport { useReactiveSnapshot } from \"@open-pioneer/reactivity\";\nimport { useCallback, useMemo, type ReactElement } from \"react\";\nimport { FeatureEditorProps, FormTemplateContext } from \"../../../api/editor/editor\";\nimport { CreationStep, UpdateStep } from \"../../../api/model/EditingStep\";\nimport { FeatureTemplate, FormTemplate } from \"../../../api/model/FeatureTemplate\";\nimport {\n DeclarativeFormContext,\n CustomFormContextImpl,\n FormContext\n} from \"../../context/PropertyFormContext\";\nimport { usePropertyFormContext } from \"../../context/usePropertyFormContext\";\nimport { EditingCallbacks } from \"../../editor/useEditingCallbacks\";\nimport { ButtonRow } from \"./ButtonRow\";\nimport { CancelConfirmationDialog } from \"./CancelConfirmationDialog\";\nimport { DeleteConfirmationDialog } from \"./DeleteConfirmationDialog\";\nimport { PropertyField } from \"./PropertyField\";\nimport { PropertyForm } from \"./PropertyForm\";\n\nexport function PropertyEditor(props: {\n editingStep: CreationStep | UpdateStep;\n callbacks: EditingCallbacks;\n templates: FeatureTemplate[];\n resolveFormTemplate: FeatureEditorProps[\"resolveFormTemplate\"];\n}) {\n const { editingStep, callbacks, templates, resolveFormTemplate } = props;\n const formTemplate = useFormTemplate(templates, resolveFormTemplate, editingStep);\n\n const context = useMemo(() => {\n if (!formTemplate) {\n return undefined;\n }\n\n if (formTemplate.kind === \"declarative\") {\n return new DeclarativeFormContext(editingStep, callbacks, formTemplate);\n } else {\n return new CustomFormContextImpl(editingStep, callbacks, formTemplate);\n }\n }, [formTemplate, editingStep, callbacks]);\n\n return (\n context &&\n formTemplate && (\n <FormContext value={context}>\n <Flex\n className=\"editor__property-editor\"\n direction=\"column\"\n height=\"full\"\n overflowY={\"hidden\"}\n >\n <PropertyForm>\n {formTemplate.kind === \"dynamic\"\n ? formTemplate.renderForm()\n : formTemplate.fields.map((field, index) => (\n // oxlint-disable-next-line react/no-array-index-key\n <PropertyField key={index} field={field} />\n ))}\n </PropertyForm>\n <EditorControls />\n </Flex>\n </FormContext>\n )\n );\n}\n\nfunction useFormTemplate(\n templates: FeatureTemplate[],\n customResolver: FeatureEditorProps[\"resolveFormTemplate\"],\n editingStep: CreationStep | UpdateStep\n): FormTemplate | undefined {\n const defaultResolver = useDefaultFormTemplateResolver(templates);\n const resolveFormTemplate = customResolver ?? defaultResolver;\n\n const feature = editingStep.feature;\n const layer = editingStep.id === \"update\" ? editingStep.layer : undefined;\n const explicitTemplate = editingStep.id === \"creation\" ? editingStep.template : undefined;\n\n return useMemo(() => {\n if (explicitTemplate) {\n return explicitTemplate;\n } else if (editingStep.id === \"update\") {\n return resolveFormTemplate({ feature, layer });\n } else {\n return undefined;\n }\n }, [explicitTemplate, editingStep.id, feature, layer, resolveFormTemplate]);\n}\n\nfunction useDefaultFormTemplateResolver(templates: FeatureTemplate[]) {\n return useCallback(\n ({ layer }: FormTemplateContext) => {\n if (layer?.id != null) {\n return templates.find(({ layerId }) => layer.id === layerId);\n } else {\n return undefined;\n }\n },\n [templates]\n );\n}\n\nfunction EditorControls(): ReactElement {\n const context = usePropertyFormContext();\n const canSave = useReactiveSnapshot(() => context.isValid, [context]);\n\n const {\n open: deleteDialogIsOpen,\n onOpen: openDeleteDialog,\n onClose: closeDeleteDialog\n } = useDisclosure();\n const {\n open: cancelDialogIsOpen,\n onOpen: openCancelDialog,\n onClose: closeCancelConfirmationDialog\n } = useDisclosure();\n\n const onSaveClick = useEvent(async () => {\n const properties = context.getPropertiesAsObject();\n context.feature.setProperties(properties);\n await context.callbacks.onSave();\n });\n\n const onDeleteClick = useEvent(async () => {\n await context.callbacks.onDelete();\n closeDeleteDialog();\n });\n\n const onConfirmCancelClick = useEvent(() => {\n context.callbacks.onCancel();\n closeCancelConfirmationDialog();\n });\n\n return (\n <>\n <ButtonRow\n canSave={canSave}\n showDeleteButton={context.mode === \"update\"}\n onSave={onSaveClick}\n onDelete={openDeleteDialog}\n onCancel={openCancelDialog}\n />\n <DeleteConfirmationDialog\n isOpen={deleteDialogIsOpen}\n onDelete={onDeleteClick}\n onCancel={closeDeleteDialog}\n />\n <CancelConfirmationDialog\n isOpen={cancelDialogIsOpen}\n onConfirmCancel={onConfirmCancelClick}\n onAbortCancel={closeCancelConfirmationDialog}\n />\n </>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PropertyField.js","sources":["PropertyField.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { Field } from \"@chakra-ui/react\";\nimport { useReactiveSnapshot } from \"@open-pioneer/reactivity\";\nimport { useIntl } from \"open-pioneer:react-hooks\";\nimport { useMemo, useState, type ReactElement } from \"react\";\nimport type { PropertyFunction, PropertyFunctionOr } from \"../../../api/fields/BaseFieldConfig\";\nimport type { FieldConfig } from \"../../../api/fields/FieldConfig\";\nimport {\n useDeclarativeFormContext,\n usePropertyFormContext\n} from \"../../context/usePropertyFormContext\";\nimport { DefaultControl } from \"../controls/DefaultControl\";\n\nexport interface PropertyFieldProps {\n readonly field: FieldConfig;\n}\n\nexport function PropertyField({ field }: PropertyFieldProps): ReactElement | undefined {\n const context = useDeclarativeFormContext();\n const isRequired = useValue(field.isRequired) ?? false;\n const isEnabled = useValue(field.isEnabled) ?? true;\n const isVisible = useValue(field.isVisible) ?? true;\n const isValid = useReactiveSnapshot(() => context.isFieldValid(field), [context, field]);\n\n const defaultErrorText = useDefaultErrorText(field);\n const errorText = useValue(field.errorText) ?? defaultErrorText;\n const helperText = useValue(field.helperText);\n\n const [hadFocus, setHadFocus] = useState(false);\n\n if (isVisible) {\n return (\n <Field.Root\n className=\"editor__property-field\"\n required={isRequired}\n disabled={!isEnabled}\n invalid={hadFocus && !isValid}\n data-editor-property-name={field.propertyName}\n onFocus={() => {\n setHadFocus(true);\n }}\n >\n <Field.Label>\n {field.label}\n <Field.RequiredIndicator />\n </Field.Label>\n <DefaultControl field={field} />\n {helperText && <Field.HelperText>{helperText}</Field.HelperText>}\n {errorText && <Field.ErrorText>{errorText}</Field.ErrorText>}\n </Field.Root>\n );\n } else {\n return undefined;\n }\n}\n\nfunction useDefaultErrorText(field: FieldConfig): string | undefined {\n const intl = useIntl();\n return useMemo(() => {\n if (field.type !== \"number-field\" || (field.min == null && field.max == null)) {\n return undefined;\n }\n\n const { min, max } = field;\n let messageId;\n if (min != null && max != null) {\n messageId = \"propertyEditor.errors.minAndMax\";\n } else if (min != null) {\n messageId = \"propertyEditor.errors.minOnly\";\n } else {\n messageId = \"propertyEditor.errors.maxOnly\";\n }\n return intl.formatMessage({ id: messageId }, { min, max });\n }, [intl, field]);\n}\n\nfunction useValue<T>(value: PropertyFunctionOr<T> | undefined): T | undefined {\n const context = usePropertyFormContext();\n\n return useReactiveSnapshot(() => {\n if (isPropertyFunction(value)) {\n const properties = context.getPropertiesAsObject();\n return value(properties);\n } else {\n return value;\n }\n }, [context, value]);\n}\n\nfunction isPropertyFunction<T>(value: PropertyFunctionOr<T>): value is PropertyFunction<T> {\n return typeof value === \"function\";\n}\n"],"names":[],"mappings":";;;;;;;;
|
|
1
|
+
{"version":3,"file":"PropertyField.js","sources":["PropertyField.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { Field } from \"@chakra-ui/react\";\nimport { useReactiveSnapshot } from \"@open-pioneer/reactivity\";\nimport { useIntl } from \"open-pioneer:react-hooks\";\nimport { useMemo, useState, type ReactElement } from \"react\";\nimport type { PropertyFunction, PropertyFunctionOr } from \"../../../api/fields/BaseFieldConfig\";\nimport type { FieldConfig } from \"../../../api/fields/FieldConfig\";\nimport {\n useDeclarativeFormContext,\n usePropertyFormContext\n} from \"../../context/usePropertyFormContext\";\nimport { DefaultControl } from \"../controls/DefaultControl\";\n\nexport interface PropertyFieldProps {\n readonly field: FieldConfig;\n}\n\nexport function PropertyField({ field }: PropertyFieldProps): ReactElement | undefined {\n const context = useDeclarativeFormContext();\n const isRequired = useValue(field.isRequired) ?? false;\n const isEnabled = useValue(field.isEnabled) ?? true;\n const isVisible = useValue(field.isVisible) ?? true;\n const isValid = useReactiveSnapshot(() => context.isFieldValid(field), [context, field]);\n\n const defaultErrorText = useDefaultErrorText(field);\n const errorText = useValue(field.errorText) ?? defaultErrorText;\n const helperText = useValue(field.helperText);\n\n const [hadFocus, setHadFocus] = useState(false);\n\n if (isVisible) {\n return (\n <Field.Root\n className=\"editor__property-field\"\n required={isRequired}\n disabled={!isEnabled}\n invalid={hadFocus && !isValid}\n data-editor-property-name={field.propertyName}\n onFocus={() => {\n setHadFocus(true);\n }}\n >\n <Field.Label>\n {field.label}\n <Field.RequiredIndicator />\n </Field.Label>\n <DefaultControl field={field} />\n {helperText && <Field.HelperText>{helperText}</Field.HelperText>}\n {errorText && <Field.ErrorText>{errorText}</Field.ErrorText>}\n </Field.Root>\n );\n } else {\n return undefined;\n }\n}\n\nfunction useDefaultErrorText(field: FieldConfig): string | undefined {\n const intl = useIntl();\n return useMemo(() => {\n if (field.type !== \"number-field\" || (field.min == null && field.max == null)) {\n return undefined;\n }\n\n const { min, max } = field;\n let messageId;\n if (min != null && max != null) {\n messageId = \"propertyEditor.errors.minAndMax\";\n } else if (min != null) {\n messageId = \"propertyEditor.errors.minOnly\";\n } else {\n messageId = \"propertyEditor.errors.maxOnly\";\n }\n return intl.formatMessage({ id: messageId }, { min, max });\n }, [intl, field]);\n}\n\nfunction useValue<T>(value: PropertyFunctionOr<T> | undefined): T | undefined {\n const context = usePropertyFormContext();\n\n return useReactiveSnapshot(() => {\n if (isPropertyFunction(value)) {\n const properties = context.getPropertiesAsObject();\n return value(properties);\n } else {\n return value;\n }\n }, [context, value]);\n}\n\nfunction isPropertyFunction<T>(value: PropertyFunctionOr<T>): value is PropertyFunction<T> {\n return typeof value === \"function\";\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
2
|
import { Flex, VStack, Text } from '@chakra-ui/react';
|
|
3
3
|
import { TitledSection, SectionHeading } from '@open-pioneer/react-utils';
|
|
4
|
+
import { useReactiveSnapshot } from '@open-pioneer/reactivity';
|
|
4
5
|
import { useIntl } from '../../../_virtual/hooks.js';
|
|
5
6
|
import { usePropertyFormContext } from '../../context/usePropertyFormContext.js';
|
|
6
|
-
import { useReactiveSnapshot } from '@open-pioneer/reactivity';
|
|
7
7
|
|
|
8
8
|
function PropertyForm(props) {
|
|
9
9
|
const { children } = props;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PropertyForm.js","sources":["PropertyForm.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { Flex, VStack, Text } from \"@chakra-ui/react\";\nimport { SectionHeading, TitledSection } from \"@open-pioneer/react-utils\";\nimport { useIntl } from \"open-pioneer:react-hooks\";\nimport { ReactNode, type ReactElement } from \"react\";\nimport { usePropertyFormContext } from \"../../context/usePropertyFormContext\";\
|
|
1
|
+
{"version":3,"file":"PropertyForm.js","sources":["PropertyForm.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { Flex, VStack, Text } from \"@chakra-ui/react\";\nimport { SectionHeading, TitledSection } from \"@open-pioneer/react-utils\";\nimport { useReactiveSnapshot } from \"@open-pioneer/reactivity\";\nimport { useIntl } from \"open-pioneer:react-hooks\";\nimport { ReactNode, type ReactElement } from \"react\";\nimport { usePropertyFormContext } from \"../../context/usePropertyFormContext\";\n\nexport interface PropertyFormProps {\n children?: ReactNode;\n}\n\nexport function PropertyForm(props: PropertyFormProps): ReactElement {\n const { children } = props;\n const heading = useHeading();\n const context = usePropertyFormContext();\n const hasRequiredFields = useReactiveSnapshot(() => context.hasRequiredFields, [context]);\n const { formatRichMessage } = useIntl();\n\n return (\n <TitledSection>\n <Flex\n className=\"editor__property-form\"\n direction={\"column\"}\n flex={1}\n overflowY=\"hidden\"\n >\n <SectionHeading mb={2} size=\"sm\">\n {heading}\n </SectionHeading>\n <VStack\n gap={4}\n align=\"stretch\"\n // for focus ring\n px=\"1px\"\n pb=\"4px\"\n flex={1}\n overflowY={\"auto\"}\n >\n {children}\n </VStack>\n {hasRequiredFields && (\n <Text\n fontSize={\"sm\"}\n aria-hidden=\"true\"\n textAlign={\"right\"}\n paddingRight={2}\n mb={2}\n >\n <Text as=\"span\" color=\"fg.error\">\n *\n </Text>{\" \"}\n {formatRichMessage({ id: \"propertyEditor.requiredFieldHint\" })}\n </Text>\n )}\n </Flex>\n </TitledSection>\n );\n}\n\nfunction useHeading() {\n const intl = useIntl();\n const { mode, formTemplate: template } = usePropertyFormContext();\n const defaultHeading = intl.formatMessage({\n id:\n mode === \"update\"\n ? \"propertyEditor.defaultEditHeading\"\n : \"propertyEditor.defaultCreateHeading\"\n });\n return template?.name ? `${defaultHeading}: ${template?.name} ` : defaultHeading;\n}\n"],"names":[],"mappings":";;;;;;;AAcO,SAAS,aAAa,KAAA,EAAwC;AACjE,EAAA,MAAM,EAAE,UAAS,GAAI,KAAA;AACrB,EAAA,MAAM,UAAU,UAAA,EAAW;AAC3B,EAAA,MAAM,UAAU,sBAAA,EAAuB;AACvC,EAAA,MAAM,oBAAoB,mBAAA,CAAoB,MAAM,QAAQ,iBAAA,EAAmB,CAAC,OAAO,CAAC,CAAA;AACxF,EAAA,MAAM,EAAE,iBAAA,EAAkB,GAAI,OAAA,EAAQ;AAEtC,EAAA,2BACK,aAAA,EAAA,EACG,QAAA,kBAAA,IAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MACG,SAAA,EAAU,uBAAA;AAAA,MACV,SAAA,EAAW,QAAA;AAAA,MACX,IAAA,EAAM,CAAA;AAAA,MACN,SAAA,EAAU,QAAA;AAAA,MAEV,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,cAAA,EAAA,EAAe,EAAA,EAAI,CAAA,EAAG,IAAA,EAAK,MACvB,QAAA,EAAA,OAAA,EACL,CAAA;AAAA,wBACA,GAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YACG,GAAA,EAAK,CAAA;AAAA,YACL,KAAA,EAAM,SAAA;AAAA,YAEN,EAAA,EAAG,KAAA;AAAA,YACH,EAAA,EAAG,KAAA;AAAA,YACH,IAAA,EAAM,CAAA;AAAA,YACN,SAAA,EAAW,MAAA;AAAA,YAEV;AAAA;AAAA,SACL;AAAA,QACC,iBAAA,oBACG,IAAA;AAAA,UAAC,IAAA;AAAA,UAAA;AAAA,YACG,QAAA,EAAU,IAAA;AAAA,YACV,aAAA,EAAY,MAAA;AAAA,YACZ,SAAA,EAAW,OAAA;AAAA,YACX,YAAA,EAAc,CAAA;AAAA,YACd,EAAA,EAAI,CAAA;AAAA,YAEJ,QAAA,EAAA;AAAA,8BAAA,GAAA,CAAC,IAAA,EAAA,EAAK,EAAA,EAAG,MAAA,EAAO,KAAA,EAAM,YAAW,QAAA,EAAA,GAAA,EAEjC,CAAA;AAAA,cAAQ,GAAA;AAAA,cACP,iBAAA,CAAkB,EAAE,EAAA,EAAI,kCAAA,EAAoC;AAAA;AAAA;AAAA;AACjE;AAAA;AAAA,GAER,EACJ,CAAA;AAER;AAEA,SAAS,UAAA,GAAa;AAClB,EAAA,MAAM,OAAO,OAAA,EAAQ;AACrB,EAAA,MAAM,EAAE,IAAA,EAAM,YAAA,EAAc,QAAA,KAAa,sBAAA,EAAuB;AAChE,EAAA,MAAM,cAAA,GAAiB,KAAK,aAAA,CAAc;AAAA,IACtC,EAAA,EACI,IAAA,KAAS,QAAA,GACH,mCAAA,GACA;AAAA,GACb,CAAA;AACD,EAAA,OAAO,UAAU,IAAA,GAAO,CAAA,EAAG,cAAc,CAAA,EAAA,EAAK,QAAA,EAAU,IAAI,CAAA,CAAA,CAAA,GAAM,cAAA;AACtE;;;;"}
|
|
@@ -20,7 +20,6 @@ export declare abstract class BaseFormContext {
|
|
|
20
20
|
get layer(): Layer | undefined;
|
|
21
21
|
abstract get isValid(): boolean;
|
|
22
22
|
abstract get hasRequiredFields(): boolean;
|
|
23
|
-
private static getPropertyEntries;
|
|
24
23
|
}
|
|
25
24
|
export declare class DeclarativeFormContext extends BaseFormContext {
|
|
26
25
|
#private;
|
|
@@ -11,7 +11,7 @@ class BaseFormContext {
|
|
|
11
11
|
this.#modificationStep = modificationStep;
|
|
12
12
|
this.callbacks = callbacks;
|
|
13
13
|
this.#formTemplate = formTemplate;
|
|
14
|
-
const entries = BaseFormContext
|
|
14
|
+
const entries = BaseFormContext.#getPropertyEntries(modificationStep.feature);
|
|
15
15
|
this.#propertiesMap = reactiveMap(entries);
|
|
16
16
|
this.#propsAsObject = computed(() => {
|
|
17
17
|
const entries2 = this.properties.entries();
|
|
@@ -43,7 +43,7 @@ class BaseFormContext {
|
|
|
43
43
|
get layer() {
|
|
44
44
|
return this.editingStep.id === "update" ? this.editingStep.layer : void 0;
|
|
45
45
|
}
|
|
46
|
-
static getPropertyEntries(feature) {
|
|
46
|
+
static #getPropertyEntries(feature) {
|
|
47
47
|
const properties = feature.getProperties();
|
|
48
48
|
const geometryName = feature.getGeometryName();
|
|
49
49
|
return Object.entries(properties).filter(([key, _]) => key !== geometryName);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PropertyFormContext.js","sources":["PropertyFormContext.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport {\n computed,\n reactive,\n reactiveMap,\n ReadonlyReactive,\n type ReactiveMap\n} from \"@conterra/reactivity-core\";\nimport type { Layer } from \"@open-pioneer/map\";\nimport type { Feature } from \"ol\";\nimport { createContext } from \"react\";\nimport type { CustomFormContext, Mode } from \"../../api/editor/context\";\nimport { PropertyFunctionOr } from \"../../api/fields/BaseFieldConfig\";\nimport { FieldConfig } from \"../../api/fields/FieldConfig\";\nimport type { ModificationStep } from \"../../api/model/EditingStep\";\nimport type {\n DeclarativeFormTemplate,\n FeatureTemplate,\n FormTemplate\n} from \"../../api/model/FeatureTemplate\";\nimport { EditingCallbacks } from \"../editor/useEditingCallbacks\";\n\nexport abstract class BaseFormContext {\n readonly #propertiesMap: ReactiveMap<string, unknown>;\n readonly #modificationStep: ModificationStep;\n readonly #formTemplate: FormTemplate;\n readonly #propsAsObject: ReadonlyReactive<Record<string, unknown>>;\n\n readonly callbacks: EditingCallbacks;\n\n constructor(\n modificationStep: ModificationStep,\n callbacks: EditingCallbacks,\n formTemplate: FormTemplate\n ) {\n this.#modificationStep = modificationStep;\n this.callbacks = callbacks;\n this.#formTemplate = formTemplate;\n\n const entries = BaseFormContext.getPropertyEntries(modificationStep.feature);\n this.#propertiesMap = reactiveMap(entries);\n this.#propsAsObject = computed(() => {\n const entries = this.properties.entries();\n const object = Object.fromEntries(entries);\n return object;\n });\n }\n\n getPropertiesAsObject(): Record<string, unknown> {\n return this.#propsAsObject.value;\n }\n\n get feature(): Feature {\n return this.editingStep.feature;\n }\n\n get mode(): Mode {\n return this.editingStep.id === \"creation\" ? \"create\" : \"update\";\n }\n\n get editingStep(): ModificationStep {\n return this.#modificationStep;\n }\n\n get properties(): ReactiveMap<string, unknown> {\n return this.#propertiesMap;\n }\n\n get formTemplate(): FormTemplate {\n return this.#formTemplate;\n }\n\n get template(): FeatureTemplate | undefined {\n return this.editingStep.id === \"creation\" ? this.editingStep.template : undefined;\n }\n\n get layer(): Layer | undefined {\n return this.editingStep.id === \"update\" ? this.editingStep.layer : undefined;\n }\n\n abstract get isValid(): boolean;\n abstract get hasRequiredFields(): boolean;\n\n private static getPropertyEntries(feature: Feature): [string, unknown][] {\n const properties = feature.getProperties();\n const geometryName = feature.getGeometryName();\n return Object.entries(properties).filter(([key, _]) => key !== geometryName);\n }\n}\n\nexport class DeclarativeFormContext extends BaseFormContext {\n readonly #isValid: ReadonlyReactive<boolean>;\n readonly #hasRequiredFields: ReadonlyReactive<boolean>;\n\n constructor(\n modificationStep: ModificationStep,\n callbacks: EditingCallbacks,\n template: DeclarativeFormTemplate\n ) {\n super(modificationStep, callbacks, template);\n\n this.#isValid = computed(() => {\n const props = this.getPropertiesAsObject();\n return this.formTemplate.fields.every((field) => this.#isFieldValidImpl(field, props));\n });\n this.#hasRequiredFields = computed(() => {\n const props = this.getPropertiesAsObject();\n return this.formTemplate.fields.some((field) => isTrue(field.isRequired, props, false));\n });\n }\n\n isFieldValid(field: FieldConfig) {\n const props = this.getPropertiesAsObject();\n return this.#isFieldValidImpl(field, props);\n }\n\n #isFieldValidImpl(field: FieldConfig, props: Record<string, unknown>) {\n const isRequired = isTrue(field.isRequired, props, false);\n const isPresent = props[field.propertyName] != null;\n if (!isRequired && !isPresent) {\n return true;\n }\n\n if (isRequired && !isPresent) {\n return false;\n }\n\n // Perform user-defined validation first.\n if (!isTrue(field.isValid, props, true)) {\n return false;\n }\n\n // Fallback/default validation for builtin rules.\n if (field.type === \"number-field\") {\n const value = props[field.propertyName] as number | undefined;\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n if (field.min != null && (!isPresent || value! < field.min)) {\n return false;\n }\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n if (field.max != null && (!isPresent || value! > field.max)) {\n return false;\n }\n }\n\n return true;\n }\n\n get isValid(): boolean {\n return this.#isValid.value;\n }\n\n override get formTemplate(): DeclarativeFormTemplate {\n // See constructor\n return super.formTemplate as DeclarativeFormTemplate;\n }\n\n get hasRequiredFields(): boolean {\n return this.#hasRequiredFields.value;\n }\n}\n\nexport class CustomFormContextImpl extends BaseFormContext implements CustomFormContext {\n readonly #isValid = reactive(false);\n\n constructor(\n modificationStep: ModificationStep,\n callbacks: EditingCallbacks,\n template: FormTemplate\n ) {\n super(modificationStep, callbacks, template);\n }\n\n get isValid(): boolean {\n return this.#isValid.value;\n }\n\n set isValid(isValid: boolean) {\n this.#isValid.value = isValid;\n }\n\n get hasRequiredFields(): boolean {\n return false;\n }\n}\n\nexport type AnyPropertyFormContext = DeclarativeFormContext | CustomFormContextImpl;\n\nexport const FormContext = createContext<AnyPropertyFormContext | undefined>(undefined);\n\nfunction isTrue(\n value: PropertyFunctionOr<boolean> | undefined,\n properties: Record<string, unknown>,\n defaultValue: boolean\n): boolean {\n if (value == null) {\n return defaultValue;\n }\n return typeof value === \"function\" ? value(properties) : value;\n}\n"],"names":["entries"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PropertyFormContext.js","sources":["PropertyFormContext.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport {\n computed,\n reactive,\n reactiveMap,\n ReadonlyReactive,\n type ReactiveMap\n} from \"@conterra/reactivity-core\";\nimport type { Layer } from \"@open-pioneer/map\";\nimport type { Feature } from \"ol\";\nimport { createContext } from \"react\";\nimport type { CustomFormContext, Mode } from \"../../api/editor/context\";\nimport { PropertyFunctionOr } from \"../../api/fields/BaseFieldConfig\";\nimport { FieldConfig } from \"../../api/fields/FieldConfig\";\nimport type { ModificationStep } from \"../../api/model/EditingStep\";\nimport type {\n DeclarativeFormTemplate,\n FeatureTemplate,\n FormTemplate\n} from \"../../api/model/FeatureTemplate\";\nimport { EditingCallbacks } from \"../editor/useEditingCallbacks\";\n\nexport abstract class BaseFormContext {\n readonly #propertiesMap: ReactiveMap<string, unknown>;\n readonly #modificationStep: ModificationStep;\n readonly #formTemplate: FormTemplate;\n readonly #propsAsObject: ReadonlyReactive<Record<string, unknown>>;\n\n readonly callbacks: EditingCallbacks;\n\n constructor(\n modificationStep: ModificationStep,\n callbacks: EditingCallbacks,\n formTemplate: FormTemplate\n ) {\n this.#modificationStep = modificationStep;\n this.callbacks = callbacks;\n this.#formTemplate = formTemplate;\n\n const entries = BaseFormContext.#getPropertyEntries(modificationStep.feature);\n this.#propertiesMap = reactiveMap(entries);\n this.#propsAsObject = computed(() => {\n const entries = this.properties.entries();\n const object = Object.fromEntries(entries);\n return object;\n });\n }\n\n getPropertiesAsObject(): Record<string, unknown> {\n return this.#propsAsObject.value;\n }\n\n get feature(): Feature {\n return this.editingStep.feature;\n }\n\n get mode(): Mode {\n return this.editingStep.id === \"creation\" ? \"create\" : \"update\";\n }\n\n get editingStep(): ModificationStep {\n return this.#modificationStep;\n }\n\n get properties(): ReactiveMap<string, unknown> {\n return this.#propertiesMap;\n }\n\n get formTemplate(): FormTemplate {\n return this.#formTemplate;\n }\n\n get template(): FeatureTemplate | undefined {\n return this.editingStep.id === \"creation\" ? this.editingStep.template : undefined;\n }\n\n get layer(): Layer | undefined {\n return this.editingStep.id === \"update\" ? this.editingStep.layer : undefined;\n }\n\n abstract get isValid(): boolean;\n abstract get hasRequiredFields(): boolean;\n\n static #getPropertyEntries(feature: Feature): [string, unknown][] {\n const properties = feature.getProperties();\n const geometryName = feature.getGeometryName();\n return Object.entries(properties).filter(([key, _]) => key !== geometryName);\n }\n}\n\nexport class DeclarativeFormContext extends BaseFormContext {\n readonly #isValid: ReadonlyReactive<boolean>;\n readonly #hasRequiredFields: ReadonlyReactive<boolean>;\n\n constructor(\n modificationStep: ModificationStep,\n callbacks: EditingCallbacks,\n template: DeclarativeFormTemplate\n ) {\n super(modificationStep, callbacks, template);\n\n this.#isValid = computed(() => {\n const props = this.getPropertiesAsObject();\n return this.formTemplate.fields.every((field) => this.#isFieldValidImpl(field, props));\n });\n this.#hasRequiredFields = computed(() => {\n const props = this.getPropertiesAsObject();\n return this.formTemplate.fields.some((field) => isTrue(field.isRequired, props, false));\n });\n }\n\n isFieldValid(field: FieldConfig) {\n const props = this.getPropertiesAsObject();\n return this.#isFieldValidImpl(field, props);\n }\n\n #isFieldValidImpl(field: FieldConfig, props: Record<string, unknown>) {\n const isRequired = isTrue(field.isRequired, props, false);\n const isPresent = props[field.propertyName] != null;\n if (!isRequired && !isPresent) {\n return true;\n }\n\n if (isRequired && !isPresent) {\n return false;\n }\n\n // Perform user-defined validation first.\n if (!isTrue(field.isValid, props, true)) {\n return false;\n }\n\n // Fallback/default validation for builtin rules.\n if (field.type === \"number-field\") {\n const value = props[field.propertyName] as number | undefined;\n // oxlint-disable-next-line @typescript-eslint/no-non-null-assertion\n if (field.min != null && (!isPresent || value! < field.min)) {\n return false;\n }\n // oxlint-disable-next-line @typescript-eslint/no-non-null-assertion\n if (field.max != null && (!isPresent || value! > field.max)) {\n return false;\n }\n }\n\n return true;\n }\n\n get isValid(): boolean {\n return this.#isValid.value;\n }\n\n override get formTemplate(): DeclarativeFormTemplate {\n // See constructor\n return super.formTemplate as DeclarativeFormTemplate;\n }\n\n get hasRequiredFields(): boolean {\n return this.#hasRequiredFields.value;\n }\n}\n\nexport class CustomFormContextImpl extends BaseFormContext implements CustomFormContext {\n readonly #isValid = reactive(false);\n\n constructor(\n modificationStep: ModificationStep,\n callbacks: EditingCallbacks,\n template: FormTemplate\n ) {\n super(modificationStep, callbacks, template);\n }\n\n get isValid(): boolean {\n return this.#isValid.value;\n }\n\n set isValid(isValid: boolean) {\n this.#isValid.value = isValid;\n }\n\n get hasRequiredFields(): boolean {\n return false;\n }\n}\n\nexport type AnyPropertyFormContext = DeclarativeFormContext | CustomFormContextImpl;\n\nexport const FormContext = createContext<AnyPropertyFormContext | undefined>(undefined);\n\nfunction isTrue(\n value: PropertyFunctionOr<boolean> | undefined,\n properties: Record<string, unknown>,\n defaultValue: boolean\n): boolean {\n if (value == null) {\n return defaultValue;\n }\n return typeof value === \"function\" ? value(properties) : value;\n}\n"],"names":["entries"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePropertyFormContext.js","sources":["usePropertyFormContext.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { useContext } from \"react\";\nimport {\n CustomFormContextImpl,\n DeclarativeFormContext,\n FormContext,\n type AnyPropertyFormContext\n} from \"./PropertyFormContext\";\n\n/**\n * Used by the property editor, internally.\n *\n * @internal\n */\nexport function usePropertyFormContext(): AnyPropertyFormContext {\n const context = useContext(FormContext);\n if (context != null) {\n return context;\n } else {\n throw new Error(\"No property form context available\");\n }\n}\n\n/**\n * Used by the property editor, internally.\n *\n * @internal\n */\nexport function useDeclarativeFormContext(): DeclarativeFormContext {\n const value = usePropertyFormContext();\n if (!(value instanceof DeclarativeFormContext)) {\n throw new Error(\"No declarative form context available\");\n }\n return value;\n}\n\n/**\n * Used for custom form contents.\n */\nexport function useCustomFormContext(): CustomFormContextImpl {\n const value = usePropertyFormContext();\n if (!(value instanceof CustomFormContextImpl)) {\n throw new Error(\"No custom form context available\");\n }\n return value;\n}\n"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"usePropertyFormContext.js","sources":["usePropertyFormContext.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { useContext } from \"react\";\nimport {\n CustomFormContextImpl,\n DeclarativeFormContext,\n FormContext,\n type AnyPropertyFormContext\n} from \"./PropertyFormContext\";\n\n/**\n * Used by the property editor, internally.\n *\n * @internal\n */\nexport function usePropertyFormContext(): AnyPropertyFormContext {\n const context = useContext(FormContext);\n if (context != null) {\n return context;\n } else {\n throw new Error(\"No property form context available\");\n }\n}\n\n/**\n * Used by the property editor, internally.\n *\n * @internal\n */\nexport function useDeclarativeFormContext(): DeclarativeFormContext {\n const value = usePropertyFormContext();\n if (!(value instanceof DeclarativeFormContext)) {\n throw new Error(\"No declarative form context available\");\n }\n return value;\n}\n\n/**\n * Used for custom form contents.\n */\nexport function useCustomFormContext(): CustomFormContextImpl {\n const value = usePropertyFormContext();\n if (!(value instanceof CustomFormContextImpl)) {\n throw new Error(\"No custom form context available\");\n }\n return value;\n}\n"],"names":[],"mappings":";;;AAgBO,SAAS,sBAAA,GAAiD;AAC7D,EAAA,MAAM,OAAA,GAAU,WAAW,WAAW,CAAA;AACtC,EAAA,IAAI,WAAW,IAAA,EAAM;AACjB,IAAA,OAAO,OAAA;AAAA,EACX,CAAA,MAAO;AACH,IAAA,MAAM,IAAI,MAAM,oCAAoC,CAAA;AAAA,EACxD;AACJ;AAOO,SAAS,yBAAA,GAAoD;AAChE,EAAA,MAAM,QAAQ,sBAAA,EAAuB;AACrC,EAAA,IAAI,EAAE,iBAAiB,sBAAA,CAAA,EAAyB;AAC5C,IAAA,MAAM,IAAI,MAAM,uCAAuC,CAAA;AAAA,EAC3D;AACA,EAAA,OAAO,KAAA;AACX;AAKO,SAAS,oBAAA,GAA8C;AAC1D,EAAA,MAAM,QAAQ,sBAAA,EAAuB;AACrC,EAAA,IAAI,EAAE,iBAAiB,qBAAA,CAAA,EAAwB;AAC3C,IAAA,MAAM,IAAI,MAAM,kCAAkC,CAAA;AAAA,EACtD;AACA,EAAA,OAAO,KAAA;AACX;;;;"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { type Layer, type MapModel } from "@open-pioneer/map";
|
|
2
2
|
import type { Vector as VectorSource } from "ol/source";
|
|
3
|
-
import type { Action } from "../components/action-selector/ActionSelector";
|
|
4
3
|
import type { EditingStep } from "../../api/model/EditingStep";
|
|
5
4
|
import type { FeatureTemplate } from "../../api/model/FeatureTemplate";
|
|
5
|
+
import type { Action } from "../components/action-selector/ActionSelector";
|
|
6
6
|
type StatePair<S> = [S, (newState: S) => void];
|
|
7
7
|
export declare function useEditingStep(onEditingStepChange: ((newStep: EditingStep) => void) | undefined): StatePair<EditingStep>;
|
|
8
8
|
export declare function useOnActionChange(mapModel: MapModel | undefined, selectableLayers: Layer[] | undefined, templates: FeatureTemplate[], setEditingStep: (newEditingStep: EditingStep) => void): (newAction: Action | undefined) => void;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useReactiveSnapshot } from '@open-pioneer/reactivity';
|
|
2
1
|
import { isLayer } from '@open-pioneer/map';
|
|
2
|
+
import { useReactiveSnapshot } from '@open-pioneer/reactivity';
|
|
3
3
|
import { Vector } from 'ol/layer.js';
|
|
4
4
|
import { useState, useEffect, useMemo, useCallback } from 'react';
|
|
5
5
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editorHooks.js","sources":["editorHooks.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport {
|
|
1
|
+
{"version":3,"file":"editorHooks.js","sources":["editorHooks.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { isLayer, type Layer, type MapModel } from \"@open-pioneer/map\";\nimport { useReactiveSnapshot } from \"@open-pioneer/reactivity\";\nimport { Vector as VectorLayer } from \"ol/layer\";\nimport type { Vector as VectorSource } from \"ol/source\";\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport type {\n DrawingStep,\n EditingStep,\n InitialStep,\n SelectionStep\n} from \"../../api/model/EditingStep\";\nimport type { FeatureTemplate } from \"../../api/model/FeatureTemplate\";\nimport type { Action } from \"../components/action-selector/ActionSelector\";\n\ntype StatePair<S> = [S, (newState: S) => void];\n\nexport function useEditingStep(\n onEditingStepChange: ((newStep: EditingStep) => void) | undefined\n): StatePair<EditingStep> {\n const [editingStep, setEditingStep] = useState<EditingStep>({ id: \"initial\" });\n\n useEffect(() => {\n onEditingStepChange?.(editingStep);\n }, [editingStep, onEditingStepChange]);\n\n return [editingStep, setEditingStep];\n}\n\nexport function useOnActionChange(\n mapModel: MapModel | undefined,\n selectableLayers: Layer[] | undefined,\n templates: FeatureTemplate[],\n setEditingStep: (newEditingStep: EditingStep) => void\n): (newAction: Action | undefined) => void {\n const defaultLayers = useDefaultLayers(mapModel, templates);\n\n return useCallback(\n (action) => {\n if (action == null) {\n setEditingStep({ id: \"initial\" } satisfies InitialStep);\n } else if (action.mode === \"update\") {\n setEditingStep({\n id: \"selection\",\n layers: selectableLayers ?? defaultLayers\n } satisfies SelectionStep);\n } else {\n setEditingStep({ id: \"drawing\", template: action.template } satisfies DrawingStep);\n }\n },\n [defaultLayers, selectableLayers, setEditingStep]\n );\n}\n\nexport function useSnappingSources(\n mapModel: MapModel | undefined,\n snappableLayers: Layer[] | undefined,\n templates: FeatureTemplate[]\n): VectorSource[] {\n const defaultLayers = useDefaultLayers(mapModel, templates);\n\n return useMemo(() => {\n return compactMap(snappableLayers ?? defaultLayers, (layer) =>\n layer.olLayer instanceof VectorLayer ? layer.olLayer.getSource() : undefined\n );\n }, [defaultLayers, snappableLayers]);\n}\n\nfunction useDefaultLayers(mapModel: MapModel | undefined, templates: FeatureTemplate[]): Layer[] {\n return useReactiveSnapshot(() => {\n const layerIds = compactMap(templates, ({ layerId }) => layerId);\n const uniqueLayerIds = new Set(layerIds);\n const layers = compactMap([...uniqueLayerIds], (id) => mapModel?.layers.getLayerById(id));\n return layers.filter((layer) => isLayer(layer));\n }, [mapModel, templates]);\n}\n\nfunction compactMap<T, U>(array: T[], mapper: (element: T) => U | undefined): U[] {\n return array.flatMap((element) => {\n const value = mapper(element);\n return value != null ? [value] : [];\n });\n}\n"],"names":["VectorLayer"],"mappings":";;;;;AAmBO,SAAS,eACZ,mBAAA,EACsB;AACtB,EAAA,MAAM,CAAC,aAAa,cAAc,CAAA,GAAI,SAAsB,EAAE,EAAA,EAAI,WAAW,CAAA;AAE7E,EAAA,SAAA,CAAU,MAAM;AACZ,IAAA,mBAAA,GAAsB,WAAW,CAAA;AAAA,EACrC,CAAA,EAAG,CAAC,WAAA,EAAa,mBAAmB,CAAC,CAAA;AAErC,EAAA,OAAO,CAAC,aAAa,cAAc,CAAA;AACvC;AAEO,SAAS,iBAAA,CACZ,QAAA,EACA,gBAAA,EACA,SAAA,EACA,cAAA,EACuC;AACvC,EAAA,MAAM,aAAA,GAAgB,gBAAA,CAAiB,QAAA,EAAU,SAAS,CAAA;AAE1D,EAAA,OAAO,WAAA;AAAA,IACH,CAAC,MAAA,KAAW;AACR,MAAA,IAAI,UAAU,IAAA,EAAM;AAChB,QAAA,cAAA,CAAe,EAAE,EAAA,EAAI,SAAA,EAAiC,CAAA;AAAA,MAC1D,CAAA,MAAA,IAAW,MAAA,CAAO,IAAA,KAAS,QAAA,EAAU;AACjC,QAAA,cAAA,CAAe;AAAA,UACX,EAAA,EAAI,WAAA;AAAA,UACJ,QAAQ,gBAAA,IAAoB;AAAA,SACP,CAAA;AAAA,MAC7B,CAAA,MAAO;AACH,QAAA,cAAA,CAAe,EAAE,EAAA,EAAI,SAAA,EAAW,QAAA,EAAU,MAAA,CAAO,UAAgC,CAAA;AAAA,MACrF;AAAA,IACJ,CAAA;AAAA,IACA,CAAC,aAAA,EAAe,gBAAA,EAAkB,cAAc;AAAA,GACpD;AACJ;AAEO,SAAS,kBAAA,CACZ,QAAA,EACA,eAAA,EACA,SAAA,EACc;AACd,EAAA,MAAM,aAAA,GAAgB,gBAAA,CAAiB,QAAA,EAAU,SAAS,CAAA;AAE1D,EAAA,OAAO,QAAQ,MAAM;AACjB,IAAA,OAAO,UAAA;AAAA,MAAW,eAAA,IAAmB,aAAA;AAAA,MAAe,CAAC,UACjD,KAAA,CAAM,OAAA,YAAmBA,SAAc,KAAA,CAAM,OAAA,CAAQ,WAAU,GAAI;AAAA,KACvE;AAAA,EACJ,CAAA,EAAG,CAAC,aAAA,EAAe,eAAe,CAAC,CAAA;AACvC;AAEA,SAAS,gBAAA,CAAiB,UAAgC,SAAA,EAAuC;AAC7F,EAAA,OAAO,oBAAoB,MAAM;AAC7B,IAAA,MAAM,WAAW,UAAA,CAAW,SAAA,EAAW,CAAC,EAAE,OAAA,OAAc,OAAO,CAAA;AAC/D,IAAA,MAAM,cAAA,GAAiB,IAAI,GAAA,CAAI,QAAQ,CAAA;AACvC,IAAA,MAAM,MAAA,GAAS,UAAA,CAAW,CAAC,GAAG,cAAc,CAAA,EAAG,CAAC,EAAA,KAAO,QAAA,EAAU,MAAA,CAAO,YAAA,CAAa,EAAE,CAAC,CAAA;AACxF,IAAA,OAAO,OAAO,MAAA,CAAO,CAAC,KAAA,KAAU,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAClD,CAAA,EAAG,CAAC,QAAA,EAAU,SAAS,CAAC,CAAA;AAC5B;AAEA,SAAS,UAAA,CAAiB,OAAY,MAAA,EAA4C;AAC9E,EAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,CAAC,OAAA,KAAY;AAC9B,IAAA,MAAM,KAAA,GAAQ,OAAO,OAAO,CAAA;AAC5B,IAAA,OAAO,KAAA,IAAS,IAAA,GAAO,CAAC,KAAK,IAAI,EAAC;AAAA,EACtC,CAAC,CAAA;AACL;;;;"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { MapModel } from "@open-pioneer/map";
|
|
2
|
-
import type { FeatureWriter } from "../../api/model/FeatureWriter";
|
|
3
2
|
import type { EditingStep } from "../../api/model/EditingStep";
|
|
3
|
+
import type { FeatureWriter } from "../../api/model/FeatureWriter";
|
|
4
4
|
export interface EditingCallbacks {
|
|
5
5
|
readonly onSave: () => Promise<void>;
|
|
6
6
|
readonly onDelete: () => Promise<void>;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { createLogger } from '@open-pioneer/core';
|
|
2
|
+
import { useEvent } from '@open-pioneer/react-utils';
|
|
2
3
|
import { useReactiveSnapshot } from '@open-pioneer/reactivity';
|
|
3
4
|
import { useService, useIntl } from '../../_virtual/hooks.js';
|
|
4
5
|
import { sourceId } from '../../_virtual/source-info.js';
|
|
5
6
|
import { useMemo, useCallback } from 'react';
|
|
6
|
-
import { useEvent } from '@open-pioneer/react-utils';
|
|
7
7
|
|
|
8
8
|
const LOG = createLogger(sourceId);
|
|
9
9
|
const INITIAL = { id: "initial" };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useEditingCallbacks.js","sources":["useEditingCallbacks.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { createLogger } from \"@open-pioneer/core\";\nimport type { MapModel } from \"@open-pioneer/map\";\nimport type { NotificationService } from \"@open-pioneer/notifier\";\nimport { useReactiveSnapshot } from \"@open-pioneer/reactivity\";\nimport { useIntl, useService } from \"open-pioneer:react-hooks\";\nimport { sourceId } from \"open-pioneer:source-info\";\nimport { useCallback, useMemo } from \"react\";\nimport type {
|
|
1
|
+
{"version":3,"file":"useEditingCallbacks.js","sources":["useEditingCallbacks.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { createLogger } from \"@open-pioneer/core\";\nimport type { MapModel } from \"@open-pioneer/map\";\nimport type { NotificationService } from \"@open-pioneer/notifier\";\nimport { useEvent } from \"@open-pioneer/react-utils\";\nimport { useReactiveSnapshot } from \"@open-pioneer/reactivity\";\nimport { useIntl, useService } from \"open-pioneer:react-hooks\";\nimport { sourceId } from \"open-pioneer:source-info\";\nimport { useCallback, useMemo } from \"react\";\nimport type { EditingStep, InitialStep } from \"../../api/model/EditingStep\";\nimport type { FeatureWriter, StorageResult } from \"../../api/model/FeatureWriter\";\n\nconst LOG = createLogger(sourceId);\n\nconst INITIAL: InitialStep = { id: \"initial\" };\n\nexport interface EditingCallbacks {\n readonly onSave: () => Promise<void>;\n readonly onDelete: () => Promise<void>;\n readonly onCancel: () => void;\n}\n\n// oxlint-disable-next-line max-params\nexport function useEditingCallbacks(\n mapModel: MapModel,\n editingStep: EditingStep,\n writer: FeatureWriter,\n setEditingStep: (newEditingStep: EditingStep) => void,\n successNotifierDisplayDuration: number | false | undefined,\n failureNotifierDisplayDuration: number | false | undefined\n): EditingCallbacks {\n const projection = useReactiveSnapshot(() => mapModel.projection, [mapModel]);\n\n const showNotifier = useShowNotifier(\n successNotifierDisplayDuration,\n failureNotifierDisplayDuration\n );\n\n const onSave = useEvent(async () => {\n if (editingStep.id === \"creation\") {\n const { feature, template } = editingStep;\n\n let result: StorageResult;\n try {\n result = await writer.addFeature({ feature, template, projection });\n setEditingStep(INITIAL);\n } catch (error) {\n LOG.error(\"Error creating feature\", feature, error);\n result = { kind: \"error\" };\n }\n showNotifier(\"create\", result);\n } else if (editingStep.id === \"update\") {\n const { feature, layer } = editingStep;\n\n let result: StorageResult;\n try {\n result = await writer.updateFeature({ feature, layer, projection });\n setEditingStep(INITIAL);\n } catch (error) {\n LOG.error(\"Error updating feature\", feature, error);\n result = { kind: \"error\" };\n }\n showNotifier(\"update\", result);\n }\n });\n const onDelete = useEvent(async () => {\n if (editingStep.id === \"update\") {\n const { feature, layer } = editingStep;\n\n let result: StorageResult;\n try {\n result = await writer.deleteFeature({ feature, layer, projection });\n setEditingStep(INITIAL);\n } catch (error) {\n LOG.error(\"Error deleting feature\", feature, error);\n result = { kind: \"error\" };\n }\n showNotifier(\"delete\", result);\n }\n });\n const onCancel = useEvent(async () => {\n setEditingStep(INITIAL);\n });\n\n return useMemo(\n () => ({\n onSave,\n onDelete,\n onCancel\n }),\n [onSave, onDelete, onCancel]\n );\n}\n\nfunction useShowNotifier(\n successNotifierDisplayDuration: number | false | undefined,\n failureNotifierDisplayDuration: number | false | undefined\n) {\n const notifier = useService<NotificationService>(\"notifier.NotificationService\");\n const { formatMessage } = useIntl();\n\n return useCallback(\n (operation: Operation, result: StorageResult) => {\n if (!result) {\n // void, undefined --> success\n if (successNotifierDisplayDuration !== false) {\n notifier.success({\n title: formatMessage({\n id: getTitleId(operation, true)\n }),\n displayDuration: successNotifierDisplayDuration\n });\n }\n } else {\n if (failureNotifierDisplayDuration !== false) {\n notifier.error({\n title: formatMessage({\n id: getTitleId(operation, false)\n }),\n message: result.message,\n displayDuration: failureNotifierDisplayDuration\n });\n }\n }\n },\n [formatMessage, notifier, successNotifierDisplayDuration, failureNotifierDisplayDuration]\n );\n}\n\nfunction getTitleId(operation: Operation, success: boolean): TitleId {\n switch (operation) {\n case \"create\":\n return success ? TitleId.CreationSuccess : TitleId.CreationFailure;\n case \"update\":\n return success ? TitleId.UpdateSuccess : TitleId.UpdateFailure;\n case \"delete\":\n return success ? TitleId.DeletionSuccess : TitleId.DeletionFailure;\n }\n}\n\nenum TitleId {\n CreationSuccess = \"notifier.creationSuccess\",\n CreationFailure = \"notifier.creationFailure\",\n UpdateSuccess = \"notifier.updateSuccess\",\n UpdateFailure = \"notifier.updateFailure\",\n DeletionSuccess = \"notifier.deletionSuccess\",\n DeletionFailure = \"notifier.deletionFailure\"\n}\n\ntype Operation = \"create\" | \"update\" | \"delete\";\n"],"names":[],"mappings":"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"}
|
|
@@ -12,12 +12,7 @@ export interface DrawingActionHandler {
|
|
|
12
12
|
readonly reset: () => void;
|
|
13
13
|
}
|
|
14
14
|
export declare class DrawingSession implements DrawingTracker, DrawingState {
|
|
15
|
-
private
|
|
16
|
-
private actionHandler;
|
|
17
|
-
private watchHandle;
|
|
18
|
-
private readonly canFinishSignal;
|
|
19
|
-
private readonly canResetSignal;
|
|
20
|
-
private readonly undoManager;
|
|
15
|
+
#private;
|
|
21
16
|
trackCapabilities(feature: Feature, actionHandler: DrawingActionHandler): void;
|
|
22
17
|
finish(): void;
|
|
23
18
|
reset(): void;
|
|
@@ -4,12 +4,12 @@ import { getNumberOfVertices, canBeFinished, canBeReset, getLastCoordinate } fro
|
|
|
4
4
|
import { UndoManager } from './UndoManager.js';
|
|
5
5
|
|
|
6
6
|
class DrawingSession {
|
|
7
|
-
ignoreNextEdit = false;
|
|
8
|
-
actionHandler;
|
|
9
|
-
watchHandle;
|
|
10
|
-
canFinishSignal = reactive();
|
|
11
|
-
canResetSignal = reactive();
|
|
12
|
-
undoManager = new UndoManager();
|
|
7
|
+
#ignoreNextEdit = false;
|
|
8
|
+
#actionHandler;
|
|
9
|
+
#watchHandle;
|
|
10
|
+
#canFinishSignal = reactive();
|
|
11
|
+
#canResetSignal = reactive();
|
|
12
|
+
#undoManager = new UndoManager();
|
|
13
13
|
trackCapabilities(feature, actionHandler) {
|
|
14
14
|
this.untrackCapabilities();
|
|
15
15
|
const geometry = feature.getGeometry();
|
|
@@ -21,70 +21,70 @@ class DrawingSession {
|
|
|
21
21
|
return () => unByKey(eventsKey);
|
|
22
22
|
}
|
|
23
23
|
);
|
|
24
|
-
this
|
|
25
|
-
this
|
|
24
|
+
this.#ignoreNextEdit = true;
|
|
25
|
+
this.#watchHandle = watchValue(
|
|
26
26
|
() => numberOfVertices.value,
|
|
27
27
|
(numberOfVertices2) => {
|
|
28
|
-
this
|
|
29
|
-
this
|
|
30
|
-
if (!this
|
|
28
|
+
this.#canFinishSignal.value = canBeFinished(geometry, numberOfVertices2);
|
|
29
|
+
this.#canResetSignal.value = canBeReset(geometry, numberOfVertices2);
|
|
30
|
+
if (!this.#ignoreNextEdit) {
|
|
31
31
|
const lastCoordinate = getLastCoordinate(geometry);
|
|
32
32
|
if (lastCoordinate != null) {
|
|
33
|
-
this
|
|
33
|
+
this.#undoManager.addEdit(lastCoordinate);
|
|
34
34
|
}
|
|
35
35
|
} else {
|
|
36
|
-
this
|
|
36
|
+
this.#ignoreNextEdit = false;
|
|
37
37
|
}
|
|
38
38
|
},
|
|
39
39
|
{ immediate: true }
|
|
40
40
|
);
|
|
41
|
-
this
|
|
41
|
+
this.#actionHandler = actionHandler;
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
finish() {
|
|
45
45
|
if (this.canFinish) {
|
|
46
|
-
this
|
|
46
|
+
this.#actionHandler?.finish();
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
reset() {
|
|
50
50
|
if (this.canReset) {
|
|
51
|
-
this
|
|
51
|
+
this.#actionHandler?.reset();
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
undo() {
|
|
55
|
-
if (this.canUndo && this
|
|
56
|
-
this
|
|
57
|
-
this
|
|
58
|
-
this
|
|
55
|
+
if (this.canUndo && this.#actionHandler != null) {
|
|
56
|
+
this.#undoManager.undo();
|
|
57
|
+
this.#ignoreNextEdit = true;
|
|
58
|
+
this.#actionHandler.undo();
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
redo() {
|
|
62
|
-
if (this.canRedo && this
|
|
63
|
-
const coordinate = this
|
|
62
|
+
if (this.canRedo && this.#actionHandler != null) {
|
|
63
|
+
const coordinate = this.#undoManager.redo();
|
|
64
64
|
if (coordinate != null) {
|
|
65
|
-
this
|
|
66
|
-
this
|
|
65
|
+
this.#ignoreNextEdit = true;
|
|
66
|
+
this.#actionHandler.redo(coordinate);
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
untrackCapabilities() {
|
|
71
|
-
this
|
|
72
|
-
this
|
|
73
|
-
this
|
|
74
|
-
this
|
|
75
|
-
this
|
|
71
|
+
this.#watchHandle?.destroy();
|
|
72
|
+
this.#canFinishSignal.value = void 0;
|
|
73
|
+
this.#canResetSignal.value = void 0;
|
|
74
|
+
this.#undoManager.reset();
|
|
75
|
+
this.#actionHandler = void 0;
|
|
76
76
|
}
|
|
77
77
|
get canFinish() {
|
|
78
|
-
return this
|
|
78
|
+
return this.#canFinishSignal.value ?? false;
|
|
79
79
|
}
|
|
80
80
|
get canReset() {
|
|
81
|
-
return this
|
|
81
|
+
return this.#canResetSignal.value ?? false;
|
|
82
82
|
}
|
|
83
83
|
get canUndo() {
|
|
84
|
-
return this
|
|
84
|
+
return this.#undoManager.canUndo;
|
|
85
85
|
}
|
|
86
86
|
get canRedo() {
|
|
87
|
-
return this
|
|
87
|
+
return this.#undoManager.canRedo;
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DrawingSession.js","sources":["DrawingSession.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { reactive, synchronized, watchValue, type CleanupHandle } from \"@conterra/reactivity-core\";\nimport type { Feature } from \"ol\";\nimport type { Coordinate } from \"ol/coordinate\";\nimport { unByKey } from \"ol/Observable\";\nimport { DrawingState } from \"../useGeometryEditing\";\nimport { canBeFinished, canBeReset, getLastCoordinate, getNumberOfVertices } from \"./geometryState\";\nimport { UndoManager } from \"./UndoManager\";\n\nexport interface DrawingTracker {\n readonly trackCapabilities: (feature: Feature, actionHandler: DrawingActionHandler) => void;\n readonly untrackCapabilities: () => void;\n}\n\nexport interface DrawingActionHandler {\n readonly undo: () => void;\n readonly redo: (coordinate: Coordinate) => void;\n readonly finish: () => void;\n readonly reset: () => void;\n}\n\nexport class DrawingSession implements DrawingTracker, DrawingState {\n
|
|
1
|
+
{"version":3,"file":"DrawingSession.js","sources":["DrawingSession.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\n\nimport { reactive, synchronized, watchValue, type CleanupHandle } from \"@conterra/reactivity-core\";\nimport type { Feature } from \"ol\";\nimport type { Coordinate } from \"ol/coordinate\";\nimport { unByKey } from \"ol/Observable\";\nimport { DrawingState } from \"../useGeometryEditing\";\nimport { canBeFinished, canBeReset, getLastCoordinate, getNumberOfVertices } from \"./geometryState\";\nimport { UndoManager } from \"./UndoManager\";\n\nexport interface DrawingTracker {\n readonly trackCapabilities: (feature: Feature, actionHandler: DrawingActionHandler) => void;\n readonly untrackCapabilities: () => void;\n}\n\nexport interface DrawingActionHandler {\n readonly undo: () => void;\n readonly redo: (coordinate: Coordinate) => void;\n readonly finish: () => void;\n readonly reset: () => void;\n}\n\nexport class DrawingSession implements DrawingTracker, DrawingState {\n #ignoreNextEdit = false;\n #actionHandler: DrawingActionHandler | undefined;\n #watchHandle: CleanupHandle | undefined;\n\n readonly #canFinishSignal = reactive<boolean>();\n readonly #canResetSignal = reactive<boolean>();\n readonly #undoManager = new UndoManager<Coordinate>();\n\n trackCapabilities(feature: Feature, actionHandler: DrawingActionHandler): void {\n this.untrackCapabilities();\n\n const geometry = feature.getGeometry();\n\n if (geometry != null) {\n const numberOfVertices = synchronized(\n () => getNumberOfVertices(geometry),\n (callback) => {\n const eventsKey = geometry.on(\"change\", callback);\n return () => unByKey(eventsKey);\n }\n );\n\n this.#ignoreNextEdit = true;\n\n // TODO: When undoing the very first change (that is, removing the first vertex),\n // a \"drawabort\" event is fired causing the undo history to be reset.\n this.#watchHandle = watchValue(\n () => numberOfVertices.value,\n (numberOfVertices) => {\n this.#canFinishSignal.value = canBeFinished(geometry, numberOfVertices);\n this.#canResetSignal.value = canBeReset(geometry, numberOfVertices);\n\n if (!this.#ignoreNextEdit) {\n const lastCoordinate = getLastCoordinate(geometry);\n if (lastCoordinate != null) {\n this.#undoManager.addEdit(lastCoordinate);\n }\n } else {\n this.#ignoreNextEdit = false;\n }\n },\n { immediate: true }\n );\n\n this.#actionHandler = actionHandler;\n }\n }\n\n finish(): void {\n if (this.canFinish) {\n this.#actionHandler?.finish();\n }\n }\n\n reset(): void {\n if (this.canReset) {\n this.#actionHandler?.reset();\n }\n }\n\n undo(): void {\n if (this.canUndo && this.#actionHandler != null) {\n this.#undoManager.undo();\n this.#ignoreNextEdit = true;\n this.#actionHandler.undo();\n }\n }\n\n redo(): void {\n if (this.canRedo && this.#actionHandler != null) {\n const coordinate = this.#undoManager.redo();\n if (coordinate != null) {\n this.#ignoreNextEdit = true;\n this.#actionHandler.redo(coordinate);\n }\n }\n }\n\n untrackCapabilities(): void {\n this.#watchHandle?.destroy();\n\n this.#canFinishSignal.value = undefined;\n this.#canResetSignal.value = undefined;\n this.#undoManager.reset();\n\n this.#actionHandler = undefined;\n }\n\n get canFinish(): boolean {\n return this.#canFinishSignal.value ?? false;\n }\n\n get canReset(): boolean {\n return this.#canResetSignal.value ?? false;\n }\n\n get canUndo(): boolean {\n return this.#undoManager.canUndo;\n }\n\n get canRedo(): boolean {\n return this.#undoManager.canRedo;\n }\n}\n"],"names":["numberOfVertices"],"mappings":"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"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { LayerFactory, MapModel } from "@open-pioneer/map";
|
|
2
|
+
import type { Type as GeometryType } from "ol/geom/Geometry";
|
|
2
3
|
import type { Vector as VectorSource } from "ol/source";
|
|
4
|
+
import { ReactNode } from "react";
|
|
3
5
|
import type { InteractionOptions } from "../../../api/model/InteractionOptions";
|
|
4
6
|
import { type DrawingParameters } from "../interactions/DrawingInteraction";
|
|
5
7
|
import { type ModificationParameters } from "../interactions/ModificationInteraction";
|
|
6
8
|
import { type SelectionParameters } from "../interactions/SelectionInteraction";
|
|
7
9
|
import { DrawingSession } from "./DrawingSession";
|
|
8
|
-
import type { Type as GeometryType } from "ol/geom/Geometry";
|
|
9
|
-
import { ReactNode } from "react";
|
|
10
10
|
type StartDrawingFeatureOptions = Required<Omit<DrawingParameters, "tracker" | "layerFactory" | "tooltipMessages">>;
|
|
11
11
|
type StartSelectingFeatureOptions = Pick<SelectionParameters, "layers" | "completionHandler">;
|
|
12
12
|
type StartModifyingFeatureOptions = Pick<ModificationParameters, "feature" | "drawLayer">;
|
|
@@ -16,12 +16,7 @@ export interface TooltipMessages {
|
|
|
16
16
|
getModificationMessages(): Map<string, ReactNode>;
|
|
17
17
|
}
|
|
18
18
|
export declare class EditingController {
|
|
19
|
-
private
|
|
20
|
-
private readonly layerFactory;
|
|
21
|
-
private readonly tooltipMessages;
|
|
22
|
-
private currentInteractions;
|
|
23
|
-
private snappingSources;
|
|
24
|
-
private interactionOptions;
|
|
19
|
+
#private;
|
|
25
20
|
readonly drawingSession: DrawingSession;
|
|
26
21
|
constructor(mapModel: MapModel, layerFactory: LayerFactory, tooltipMessages: TooltipMessages);
|
|
27
22
|
startDrawingFeature({ geometryType, drawingOptions, completionHandler }: StartDrawingFeatureOptions): void;
|
|
@@ -30,6 +25,5 @@ export declare class EditingController {
|
|
|
30
25
|
setSnappingSources(sources: VectorSource[] | undefined): void;
|
|
31
26
|
setInteractionOptions(options: InteractionOptions): void;
|
|
32
27
|
stopCurrentInteractions(): void;
|
|
33
|
-
private replaceInteractions;
|
|
34
28
|
}
|
|
35
29
|
export {};
|