@dative-gpi/foundation-shared-components 0.0.206 → 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/FSClock.vue +2 -6
- package/components/FSImageCard.vue +72 -0
- package/components/fields/FSDateTimeField.vue +2 -6
- package/components/fields/FSDateTimeRangeField.vue +2 -6
- package/components/fields/FSRichTextField.vue +132 -54
- package/components/fields/FSTermField.vue +2 -6
- package/components/fields/FSTimeField.vue +2 -6
- 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
|
@@ -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;
|