@dative-gpi/foundation-shared-components 0.0.205 → 0.0.207
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/assets/images/map/imagery.png +0 -0
- package/assets/images/map/osm.png +0 -0
- package/components/FSCalendar.vue +1 -0
- package/components/FSCalendarTwin.vue +2 -1
- package/components/FSClock.vue +18 -6
- package/components/FSImageCard.vue +72 -0
- package/components/autocompletes/FSAutoCompleteAddress.vue +6 -6
- package/components/autocompletes/FSAutocompleteLanguage.vue +4 -5
- package/components/autocompletes/FSAutocompleteTimeZone.vue +4 -5
- package/components/fields/FSColorField.vue +9 -11
- package/components/fields/FSDateField.vue +10 -4
- package/components/fields/FSDateRangeField.vue +10 -4
- package/components/fields/FSDateTimeField.vue +20 -11
- package/components/fields/FSDateTimeRangeField.vue +35 -25
- package/components/fields/FSRichTextField.vue +132 -54
- package/components/fields/FSTermField.vue +190 -186
- package/components/fields/FSTimeField.vue +17 -12
- package/components/fields/FSTranslateField.vue +7 -14
- package/components/fields/FSTranslateRichTextField.vue +185 -0
- package/components/map/FSMap.vue +129 -65
- package/components/map/FSMapEditPointAddressOverlay.vue +19 -18
- package/components/map/FSMapLayerButton.vue +71 -0
- package/models/map.ts +1 -0
- package/models/richTextVariable.ts +5 -0
- package/models/variableNode.ts +105 -0
- package/package.json +4 -4
- package/styles/components/fs_image_card.scss +18 -0
- package/styles/components/fs_map.scss +10 -14
- package/styles/components/fs_rich_text_field.scss +16 -4
- package/styles/components/index.scss +1 -0
- package/utils/lexical.ts +2 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<FSCard
|
|
3
3
|
padding="16px"
|
|
4
|
-
width="100%"
|
|
5
4
|
height="100%"
|
|
5
|
+
width="100%"
|
|
6
6
|
:elevation="true"
|
|
7
7
|
>
|
|
8
8
|
<FSCol
|
|
@@ -50,11 +50,11 @@
|
|
|
50
50
|
/>
|
|
51
51
|
</FSRow>
|
|
52
52
|
<FSButton
|
|
53
|
-
|
|
53
|
+
prependIcon="mdi-content-save"
|
|
54
|
+
style="display: none;"
|
|
54
55
|
color="primary"
|
|
55
|
-
prepend-icon="mdi-content-save"
|
|
56
56
|
type="submit"
|
|
57
|
-
|
|
57
|
+
:label="$tr('ui.map.save', 'Save')"
|
|
58
58
|
/>
|
|
59
59
|
</FSForm>
|
|
60
60
|
</FSCol>
|
|
@@ -66,9 +66,9 @@
|
|
|
66
66
|
@click="onCancel"
|
|
67
67
|
/>
|
|
68
68
|
<FSButton
|
|
69
|
-
|
|
69
|
+
prependIcon="mdi-content-save"
|
|
70
70
|
color="primary"
|
|
71
|
-
|
|
71
|
+
:label="$tr('ui.map.save', 'Save')"
|
|
72
72
|
@click="onSubmit"
|
|
73
73
|
/>
|
|
74
74
|
</FSRow>
|
|
@@ -104,17 +104,16 @@ export default defineComponent({
|
|
|
104
104
|
},
|
|
105
105
|
props: {
|
|
106
106
|
modelValue: {
|
|
107
|
-
type: Object as PropType<Address>,
|
|
108
|
-
default: null
|
|
109
|
-
required: false,
|
|
107
|
+
type: Object as PropType<Address | null>,
|
|
108
|
+
default: null
|
|
110
109
|
}
|
|
111
110
|
},
|
|
112
111
|
emits: ["update:modelValue", "update:locationCoordinates", "submit", "cancel"],
|
|
113
112
|
setup(props, { emit }) {
|
|
114
113
|
const menuLocationCoordinates = ref(false);
|
|
115
114
|
|
|
116
|
-
const latitude = ref(
|
|
117
|
-
const longitude = ref(
|
|
115
|
+
const latitude = ref(0);
|
|
116
|
+
const longitude = ref(0);
|
|
118
117
|
|
|
119
118
|
const onCoordinatesChange = () => {
|
|
120
119
|
const newModelValue = new Address({
|
|
@@ -130,7 +129,7 @@ export default defineComponent({
|
|
|
130
129
|
};
|
|
131
130
|
|
|
132
131
|
const onAddressFieldSubmit = (address: Address|null) => {
|
|
133
|
-
if(address
|
|
132
|
+
if(!address) {
|
|
134
133
|
return;
|
|
135
134
|
}
|
|
136
135
|
emit('update:modelValue', address);
|
|
@@ -144,10 +143,12 @@ export default defineComponent({
|
|
|
144
143
|
emit('cancel');
|
|
145
144
|
};
|
|
146
145
|
|
|
147
|
-
watch(() => props.modelValue, (
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
146
|
+
watch(() => props.modelValue, () => {
|
|
147
|
+
if (props.modelValue) {
|
|
148
|
+
latitude.value = props.modelValue.latitude;
|
|
149
|
+
longitude.value = props.modelValue.longitude;
|
|
150
|
+
}
|
|
151
|
+
}, { immediate: true });
|
|
151
152
|
|
|
152
153
|
return {
|
|
153
154
|
menuLocationCoordinates,
|
|
@@ -155,8 +156,8 @@ export default defineComponent({
|
|
|
155
156
|
latitude,
|
|
156
157
|
onAddressFieldSubmit,
|
|
157
158
|
onCoordinatesChange,
|
|
158
|
-
|
|
159
|
-
|
|
159
|
+
onCancel,
|
|
160
|
+
onSubmit
|
|
160
161
|
};
|
|
161
162
|
}
|
|
162
163
|
});
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<FSButton
|
|
3
|
+
prependIcon="mdi-layers-outline"
|
|
4
|
+
:elevation="true"
|
|
5
|
+
@click="dialog = true"
|
|
6
|
+
/>
|
|
7
|
+
<FSDialog
|
|
8
|
+
v-model="dialog"
|
|
9
|
+
title="Select Layers"
|
|
10
|
+
width="460px"
|
|
11
|
+
>
|
|
12
|
+
<template
|
|
13
|
+
v-slot:body
|
|
14
|
+
>
|
|
15
|
+
<FSImageCard
|
|
16
|
+
v-for="layer in layers"
|
|
17
|
+
:variant="modelValue === layer.name ? 'full' : 'background'"
|
|
18
|
+
:color="modelValue === layer.name ? 'primary' : 'light'"
|
|
19
|
+
:label="layer.label"
|
|
20
|
+
:src="layer.image"
|
|
21
|
+
:key="layer.name"
|
|
22
|
+
@click="onLayerClick(layer.name)"
|
|
23
|
+
/>
|
|
24
|
+
</template>
|
|
25
|
+
</FSDialog>
|
|
26
|
+
</template>
|
|
27
|
+
|
|
28
|
+
<script lang="ts">
|
|
29
|
+
import { defineComponent, type PropType, ref } from "vue";
|
|
30
|
+
|
|
31
|
+
import { type MapLayer } from "../../models";
|
|
32
|
+
|
|
33
|
+
import FSImageCard from "../FSImageCard.vue";
|
|
34
|
+
import FSButton from "../FSButton.vue";
|
|
35
|
+
import FSDialog from "../FSDialog.vue";
|
|
36
|
+
|
|
37
|
+
export default defineComponent({
|
|
38
|
+
name: "FSMapLayerButton",
|
|
39
|
+
components: {
|
|
40
|
+
FSImageCard,
|
|
41
|
+
FSButton,
|
|
42
|
+
FSDialog
|
|
43
|
+
},
|
|
44
|
+
props: {
|
|
45
|
+
layers: {
|
|
46
|
+
type: Array as PropType<MapLayer[]>,
|
|
47
|
+
required: false,
|
|
48
|
+
default: () => []
|
|
49
|
+
},
|
|
50
|
+
modelValue: {
|
|
51
|
+
type: String,
|
|
52
|
+
required: false,
|
|
53
|
+
default: ""
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
emits: ["update:modelValue"],
|
|
57
|
+
setup(_, { emit }) {
|
|
58
|
+
const dialog = ref(false);
|
|
59
|
+
|
|
60
|
+
const onLayerClick = (layer: string) => {
|
|
61
|
+
emit("update:modelValue", layer);
|
|
62
|
+
dialog.value = false;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
dialog,
|
|
67
|
+
onLayerClick
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
</script>
|
package/models/map.ts
CHANGED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { type LexicalNode, DecoratorNode, type SerializedLexicalNode, type Spread, type EditorConfig, type LexicalEditor } from "lexical";
|
|
2
|
+
import type { RichTextVariable } from "./richTextVariable";
|
|
3
|
+
|
|
4
|
+
export type SerializedVariableNode = Spread<
|
|
5
|
+
{
|
|
6
|
+
type: "variable";
|
|
7
|
+
code: string;
|
|
8
|
+
defaultValue: string;
|
|
9
|
+
typeName: string;
|
|
10
|
+
},
|
|
11
|
+
SerializedLexicalNode
|
|
12
|
+
>;
|
|
13
|
+
|
|
14
|
+
export class VariableNode extends DecoratorNode<Element> {
|
|
15
|
+
__code: string;
|
|
16
|
+
__defaultValue: string;
|
|
17
|
+
__typeName: string;
|
|
18
|
+
readonlyMode: boolean;
|
|
19
|
+
|
|
20
|
+
static getType() {
|
|
21
|
+
return "variable";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
static clone(node: VariableNode) {
|
|
25
|
+
return new VariableNode(node.__code, node.__defaultValue, node.__typeName, node.__key);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
constructor(code: string, defaultValue: string, typeName: string, key?: string) {
|
|
29
|
+
super(key);
|
|
30
|
+
this.__code = code;
|
|
31
|
+
this.__defaultValue = defaultValue;
|
|
32
|
+
this.__typeName = typeName;
|
|
33
|
+
this.readonlyMode = false;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
getValue(editorElement: HTMLElement): any {
|
|
37
|
+
const variableValues = editorElement.dataset.variableValues;
|
|
38
|
+
if (!variableValues) { return this.__defaultValue; }
|
|
39
|
+
const values = JSON.parse(variableValues);
|
|
40
|
+
return values[this.__code] ?? this.__defaultValue;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
createDOM(_config: EditorConfig, _editor: LexicalEditor) {
|
|
44
|
+
const readonlyMode = _editor._rootElement?.dataset.readonly === "true" || false;
|
|
45
|
+
|
|
46
|
+
const container = document.createElement("span");
|
|
47
|
+
container.classList.add("fs-richtextfield-node-variable");
|
|
48
|
+
|
|
49
|
+
const content = document.createElement("span");
|
|
50
|
+
if (readonlyMode) {
|
|
51
|
+
content.classList.add("fs-rich-text-field-node-variable-value");
|
|
52
|
+
if (_editor._rootElement) {
|
|
53
|
+
content.textContent = this.getValue(_editor._rootElement);
|
|
54
|
+
} else {
|
|
55
|
+
content.textContent = this.__defaultValue;
|
|
56
|
+
}
|
|
57
|
+
} else {
|
|
58
|
+
content.classList.add("fs-rich-text-field-node-variable-code");
|
|
59
|
+
content.textContent = `{${this.__code}}`
|
|
60
|
+
}
|
|
61
|
+
container.appendChild(content);
|
|
62
|
+
return container;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
updateDOM(): boolean {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
exportJSON(): SerializedVariableNode {
|
|
70
|
+
return {
|
|
71
|
+
type: "variable",
|
|
72
|
+
version: 1,
|
|
73
|
+
code: this.__code,
|
|
74
|
+
defaultValue: this.__defaultValue,
|
|
75
|
+
typeName: this.__typeName,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
decorate(editor: LexicalEditor, config: EditorConfig): Element {
|
|
80
|
+
return this.createDOM(config, editor);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
static importJSON(serializedNode: SerializedVariableNode): VariableNode {
|
|
84
|
+
return new VariableNode(
|
|
85
|
+
serializedNode.code,
|
|
86
|
+
serializedNode.defaultValue,
|
|
87
|
+
serializedNode.typeName
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function $createVariableNode(code: string, defaultValue: string, typeName: string): VariableNode {
|
|
93
|
+
return new VariableNode(code, defaultValue, typeName);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function $modifyVariableNode(node: VariableNode, newValue: RichTextVariable): VariableNode {
|
|
97
|
+
node.__code = newValue.code;
|
|
98
|
+
node.__defaultValue = newValue.defaultValue;
|
|
99
|
+
node.__typeName = newValue.typeName;
|
|
100
|
+
return node;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function $isVariableNode(node: LexicalNode | null | undefined): node is VariableNode {
|
|
104
|
+
return node instanceof VariableNode;
|
|
105
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dative-gpi/foundation-shared-components",
|
|
3
3
|
"sideEffects": false,
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.207",
|
|
5
5
|
"description": "",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public"
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
"author": "",
|
|
11
11
|
"license": "ISC",
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@dative-gpi/foundation-shared-domain": "0.0.
|
|
14
|
-
"@dative-gpi/foundation-shared-services": "0.0.
|
|
13
|
+
"@dative-gpi/foundation-shared-domain": "0.0.207",
|
|
14
|
+
"@dative-gpi/foundation-shared-services": "0.0.207"
|
|
15
15
|
},
|
|
16
16
|
"peerDependencies": {
|
|
17
17
|
"@dative-gpi/bones-ui": "^0.0.75",
|
|
@@ -35,5 +35,5 @@
|
|
|
35
35
|
"sass": "1.71.1",
|
|
36
36
|
"sass-loader": "13.3.2"
|
|
37
37
|
},
|
|
38
|
-
"gitHead": "
|
|
38
|
+
"gitHead": "1387dbf5d3b11c281c0e6183ab900e47c9622a9a"
|
|
39
39
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
.fs-image-card {
|
|
2
|
+
> .fs-card {
|
|
3
|
+
background-image: var(--fs-image-card-background);
|
|
4
|
+
background-size: 100%;
|
|
5
|
+
background-position: center;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.fs-image-card-label {
|
|
9
|
+
background-color: #0000009d;
|
|
10
|
+
color: white;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.fs-image-card:hover {
|
|
15
|
+
> .fs-card {
|
|
16
|
+
background-size: 105%;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -9,21 +9,12 @@
|
|
|
9
9
|
filter: grayscale(var(--fs-map-container-grayscale));
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
.fs-map-overlay-
|
|
12
|
+
.fs-map-overlay-left {
|
|
13
13
|
position: absolute;
|
|
14
14
|
top: 0;
|
|
15
15
|
left: 0;
|
|
16
16
|
z-index: 950;
|
|
17
17
|
margin: 8px;
|
|
18
|
-
|
|
19
|
-
>* {
|
|
20
|
-
opacity: 0.7;
|
|
21
|
-
transition: opacity 0.28s cubic-bezier(0.4, 0, 0.2, 1);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
>*:hover {
|
|
25
|
-
opacity: 1;
|
|
26
|
-
}
|
|
27
18
|
}
|
|
28
19
|
|
|
29
20
|
.fs-map-overlay-edit-button {
|
|
@@ -34,10 +25,17 @@
|
|
|
34
25
|
margin: 8px;
|
|
35
26
|
}
|
|
36
27
|
|
|
37
|
-
.fs-map-overlay-
|
|
28
|
+
.fs-map-overlay-right-top {
|
|
29
|
+
position: absolute;
|
|
30
|
+
top: 0;
|
|
31
|
+
right: 0;
|
|
32
|
+
margin: 4px 8px;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.fs-map-overlay-right-bottom {
|
|
38
36
|
position: absolute;
|
|
39
37
|
bottom: 0;
|
|
40
|
-
|
|
38
|
+
right: 0;
|
|
41
39
|
z-index: 1000;
|
|
42
40
|
margin: 4px 8px;
|
|
43
41
|
width: calc(100% - 16px);
|
|
@@ -61,8 +59,6 @@
|
|
|
61
59
|
border-top-right-radius: 0 !important;
|
|
62
60
|
|
|
63
61
|
border-top: solid 1px var(--fs-card-border-color) !important;
|
|
64
|
-
|
|
65
|
-
|
|
66
62
|
}
|
|
67
63
|
}
|
|
68
64
|
}
|
|
@@ -1,19 +1,31 @@
|
|
|
1
1
|
.fs-rich-text-field {
|
|
2
2
|
width: 100%;
|
|
3
3
|
min-width: 120px;
|
|
4
|
-
outline: none !important;
|
|
5
4
|
border: 1px solid var(--fs-rich-text-field-border-color) !important;
|
|
6
5
|
border-radius: 4px !important;
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
color: var(--fs-rich-text-field-color);
|
|
7
|
+
|
|
10
8
|
margin: 2px 2px 2px 0 !important;
|
|
11
9
|
|
|
10
|
+
.fs-rich-text-field-content {
|
|
11
|
+
color: var(--fs-rich-text-field-color);
|
|
12
|
+
width: 100%;
|
|
13
|
+
min-height: var(--fs-rich-text-field-min-height);
|
|
14
|
+
outline: none !important;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.fs-richtextfield-node-variable {
|
|
18
|
+
.fs-rich-text-field-node-variable-code {
|
|
19
|
+
background-color: var(--fs-rich-text-field-variable-backgroundcolor);
|
|
20
|
+
color: var(--fs-rich-text-field-variable-color);
|
|
21
|
+
border-radius: 4px;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
12
24
|
|
|
13
25
|
&:focus-within {
|
|
14
26
|
border-color: var(--fs-rich-text-field-active-border-color) !important;
|
|
15
27
|
}
|
|
16
|
-
|
|
28
|
+
|
|
17
29
|
@include web {
|
|
18
30
|
padding: 10px 12px !important;
|
|
19
31
|
}
|
package/utils/lexical.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { ElementNode, LexicalNode, RangeSelection, TextNode } from "lexical";
|
|
2
2
|
import { $isAtNodeEnd } from "@lexical/selection";
|
|
3
3
|
|
|
4
|
+
export const emptyLexicalState = "{\"root\":{\"children\":[{\"children\":[],\"direction\":null,\"format\":\"\",\"indent\":0,\"type\":\"paragraph\",\"version\":1}],\"direction\":null,\"format\":\"\",\"indent\":0,\"type\":\"root\",\"version\":1}}";
|
|
5
|
+
|
|
4
6
|
export const getSelectedNode = (selection: RangeSelection): ElementNode | TextNode => {
|
|
5
7
|
const anchor = selection.anchor;
|
|
6
8
|
const focus = selection.focus;
|