@dative-gpi/foundation-shared-components 0.0.45 → 0.0.46

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.
@@ -2,30 +2,43 @@
2
2
  <FSCol
3
3
  width="hug"
4
4
  >
5
- <FSRow
6
- width="hug"
7
- align="center-left"
5
+ <v-checkbox
6
+ hide-details
7
+ :ripple="false"
8
+ :rules="$props.rules"
9
+ :validateOn="validateOn"
10
+ :modelValue="$props.modelValue"
11
+ @click.prevent
12
+ @blur="blurred = true"
13
+ v-bind="$attrs"
8
14
  >
9
- <FSIcon
10
- class="fs-checkbox"
11
- size="l"
12
- :style="style"
13
- @click.stop="onToggle"
14
- >
15
- {{ icon }}
16
- </FSIcon>
17
- <slot>
18
- <FSSpan
19
- v-if="$props.label"
20
- class="fs-checkbox-label"
15
+ <template #input>
16
+ <FSRow
17
+ align="center-left"
18
+ width="hug"
21
19
  :style="style"
22
- :font="font"
23
20
  @click.stop="onToggle"
24
21
  >
25
- {{ $props.label }}
26
- </FSSpan>
27
- </slot>
28
- </FSRow>
22
+ <FSIcon
23
+ class="fs-checkbox"
24
+ size="l"
25
+ :style="style"
26
+ >
27
+ {{ icon }}
28
+ </FSIcon>
29
+ <slot>
30
+ <FSSpan
31
+ v-if="$props.label"
32
+ class="fs-checkbox-label"
33
+ :style="style"
34
+ :font="font"
35
+ >
36
+ {{ $props.label }}
37
+ </FSSpan>
38
+ </slot>
39
+ </FSRow>
40
+ </template>
41
+ </v-checkbox>
29
42
  <slot name="description">
30
43
  <FSSpan
31
44
  v-if="$props.description"
@@ -42,8 +55,8 @@
42
55
  <script lang="ts">
43
56
  import { computed, defineComponent, PropType } from "vue";
44
57
 
58
+ import { useColors, useRules } from "@dative-gpi/foundation-shared-components/composables";
45
59
  import { ColorBase, ColorEnum } from "@dative-gpi/foundation-shared-components/models";
46
- import { useColors } from "@dative-gpi/foundation-shared-components/composables";
47
60
 
48
61
  import FSIcon from "./FSIcon.vue";
49
62
  import FSSpan from "./FSSpan.vue";
@@ -74,15 +87,25 @@ export default defineComponent({
74
87
  required: false,
75
88
  default: false
76
89
  },
90
+ indeterminate: {
91
+ type: Boolean,
92
+ required: false,
93
+ default: false
94
+ },
77
95
  color: {
78
96
  type: String as PropType<ColorBase>,
79
97
  required: false,
80
98
  default: ColorEnum.Primary
81
99
  },
82
- indeterminate: {
83
- type: Boolean,
100
+ rules: {
101
+ type: Array as PropType<Function[]>,
84
102
  required: false,
85
- default: false
103
+ default: () => []
104
+ },
105
+ messages: {
106
+ type: Array as PropType<string[]>,
107
+ required: false,
108
+ default: null
86
109
  },
87
110
  editable: {
88
111
  type: Boolean,
@@ -92,9 +115,11 @@ export default defineComponent({
92
115
  },
93
116
  emits: ["update:modelValue"],
94
117
  setup(props, { emit }) {
118
+ const { validateOn, blurred, getMessages } = useRules();
95
119
  const { getColors } = useColors();
96
120
 
97
121
  const colors = computed(() => getColors(props.color));
122
+ const errors = getColors(ColorEnum.Error);
98
123
  const lights = getColors(ColorEnum.Light);
99
124
  const darks = getColors(ColorEnum.Dark);
100
125
 
@@ -106,6 +131,13 @@ export default defineComponent({
106
131
  "--fs-checkbox-color" : lights.dark
107
132
  };
108
133
  }
134
+ if (messages.value.length) {
135
+ return {
136
+ "--fs-checkbox-cursor" : "pointer",
137
+ "--fs-checkbox-checkbox-color": errors.base,
138
+ "--fs-checkbox-color" : darks.base
139
+ }
140
+ }
109
141
  return {
110
142
  "--fs-checkbox-cursor" : "pointer",
111
143
  "--fs-checkbox-checkbox-color": (props.modelValue || props.indeterminate) ? colors.value.base : darks.base,
@@ -117,6 +149,8 @@ export default defineComponent({
117
149
 
118
150
  const font = computed((): string => props.modelValue ? "text-button" : "text-body");
119
151
 
152
+ const messages = computed((): string[] => props.messages ?? getMessages(props.modelValue, props.rules));
153
+
120
154
  const onToggle = (): void => {
121
155
  if (!props.editable) {
122
156
  return;
@@ -125,6 +159,9 @@ export default defineComponent({
125
159
  };
126
160
 
127
161
  return {
162
+ validateOn,
163
+ messages,
164
+ blurred,
128
165
  style,
129
166
  icon,
130
167
  font,
@@ -1,26 +1,44 @@
1
1
  <template>
2
- <FSCol width="hug">
3
- <FSRow width="hug" align="center-left">
4
- <FSIcon
5
- class="fs-radio"
6
- size="l"
7
- :style="style"
8
- @click.stop="onToggle"
9
- >
10
- {{ icon }}
11
- </FSIcon>
12
- <slot>
13
- <FSSpan
14
- v-if="$props.label"
15
- class="fs-radio-label"
2
+ <FSCol
3
+ width="hug"
4
+ >
5
+ <v-radio
6
+ hide-details
7
+ :ripple="false"
8
+ :rules="$props.rules"
9
+ :validateOn="validateOn"
10
+ :modelValue="$props.selected"
11
+ @click.prevent
12
+ @blur="blurred = true"
13
+ v-bind="$attrs"
14
+ >
15
+ <template #input>
16
+ <FSRow
17
+ align="center-left"
18
+ width="hug"
16
19
  :style="style"
17
- :font="font"
18
20
  @click.stop="onToggle"
19
21
  >
20
- {{ $props.label }}
21
- </FSSpan>
22
- </slot>
23
- </FSRow>
22
+ <FSIcon
23
+ class="fs-radio"
24
+ size="l"
25
+ :style="style"
26
+ >
27
+ {{ icon }}
28
+ </FSIcon>
29
+ <slot>
30
+ <FSSpan
31
+ v-if="$props.label"
32
+ class="fs-radio-label"
33
+ :style="style"
34
+ :font="font"
35
+ >
36
+ {{ $props.label }}
37
+ </FSSpan>
38
+ </slot>
39
+ </FSRow>
40
+ </template>
41
+ </v-radio>
24
42
  <slot name="description">
25
43
  <FSSpan
26
44
  v-if="$props.description"
@@ -37,8 +55,8 @@
37
55
  <script lang="ts">
38
56
  import { computed, defineComponent, PropType } from "vue";
39
57
 
58
+ import { useColors, useRules } from "@dative-gpi/foundation-shared-components/composables";
40
59
  import { ColorBase, ColorEnum } from "@dative-gpi/foundation-shared-components/models";
41
- import { useColors } from "@dative-gpi/foundation-shared-components/composables";
42
60
 
43
61
  import FSIcon from "./FSIcon.vue";
44
62
  import FSSpan from "./FSSpan.vue";
@@ -78,6 +96,16 @@ export default defineComponent({
78
96
  required: false,
79
97
  default: ColorEnum.Primary
80
98
  },
99
+ rules: {
100
+ type: Array as PropType<Function[]>,
101
+ required: false,
102
+ default: () => []
103
+ },
104
+ messages: {
105
+ type: Array as PropType<string[]>,
106
+ required: false,
107
+ default: null
108
+ },
81
109
  editable: {
82
110
  type: Boolean,
83
111
  required: false,
@@ -86,9 +114,11 @@ export default defineComponent({
86
114
  },
87
115
  emits: ["update:modelValue"],
88
116
  setup(props, { emit }) {
117
+ const { validateOn, blurred, getMessages } = useRules();
89
118
  const { getColors } = useColors();
90
119
 
91
120
  const colors = computed(() => getColors(props.color));
121
+ const errors = getColors(ColorEnum.Error);
92
122
  const lights = getColors(ColorEnum.Light);
93
123
  const darks = getColors(ColorEnum.Dark);
94
124
 
@@ -100,6 +130,13 @@ export default defineComponent({
100
130
  "--fs-radio-color" : lights.dark
101
131
  };
102
132
  }
133
+ if (messages.value.length) {
134
+ return {
135
+ "--fs-radio-cursor" : "pointer",
136
+ "--fs-radio-radio-color": errors.base,
137
+ "--fs-radio-color" : darks.base
138
+ }
139
+ }
103
140
  return {
104
141
  "--fs-radio-cursor" : props.selected ? "default" : "pointer",
105
142
  "--fs-radio-radio-color": props.selected ? colors.value.base : darks.base,
@@ -111,6 +148,8 @@ export default defineComponent({
111
148
 
112
149
  const font = computed((): string => props.selected ? "text-button" : "text-body");
113
150
 
151
+ const messages = computed((): string[] => props.messages ?? getMessages(props.modelValue, props.rules));
152
+
114
153
  const onToggle = (): void => {
115
154
  if (!props.editable) {
116
155
  return;
@@ -121,6 +160,9 @@ export default defineComponent({
121
160
  };
122
161
 
123
162
  return {
163
+ validateOn,
164
+ messages,
165
+ blurred,
124
166
  style,
125
167
  icon,
126
168
  font,
@@ -12,6 +12,8 @@
12
12
  inset
13
13
  :style="style"
14
14
  :ripple="false"
15
+ :rules="$props.rules"
16
+ :validateOn="validateOn"
15
17
  :modelValue="$props.modelValue"
16
18
  @update:modelValue="onToggle"
17
19
  v-bind="$attrs"
@@ -44,8 +46,8 @@
44
46
  <script lang="ts">
45
47
  import { computed, defineComponent, PropType } from "vue";
46
48
 
49
+ import { useColors, useRules } from "@dative-gpi/foundation-shared-components/composables";
47
50
  import { ColorBase, ColorEnum } from "@dative-gpi/foundation-shared-components/models";
48
- import { useColors } from "@dative-gpi/foundation-shared-components/composables";
49
51
 
50
52
  import FSSpan from "./FSSpan.vue";
51
53
  import FSCol from "./FSCol.vue";
@@ -79,6 +81,16 @@ export default defineComponent({
79
81
  required: false,
80
82
  default: ColorEnum.Primary
81
83
  },
84
+ rules: {
85
+ type: Array as PropType<Function[]>,
86
+ required: false,
87
+ default: () => []
88
+ },
89
+ messages: {
90
+ type: Array as PropType<string[]>,
91
+ required: false,
92
+ default: null
93
+ },
82
94
  editable: {
83
95
  type: Boolean,
84
96
  required: false,
@@ -87,10 +99,12 @@ export default defineComponent({
87
99
  },
88
100
  emits: ["update:modelValue"],
89
101
  setup(props, { emit }) {
102
+ const { validateOn, blurred, getMessages } = useRules();
90
103
  const { getColors } = useColors();
91
104
 
92
105
  const colors = computed(() => getColors(props.color));
93
106
  const backgrounds = getColors(ColorEnum.Background);
107
+ const errors = getColors(ColorEnum.Error);
94
108
  const lights = getColors(ColorEnum.Light);
95
109
  const darks = getColors(ColorEnum.Dark);
96
110
 
@@ -104,6 +118,15 @@ export default defineComponent({
104
118
  "--fs-switch-color" : lights.dark
105
119
  };
106
120
  }
121
+ if (messages.value.length) {
122
+ return {
123
+ "--fs-switch-translate-x": props.modelValue ? "8px" : "-8px",
124
+ "--fs-switch-cursor" : "pointer",
125
+ "--fs-switch-track-color": errors.base,
126
+ "--fs-switch-thumb-color": backgrounds.base,
127
+ "--fs-switch-color" : darks.base
128
+ };
129
+ }
107
130
  return {
108
131
  "--fs-switch-translate-x": props.modelValue ? "8px" : "-8px",
109
132
  "--fs-switch-cursor" : "pointer",
@@ -115,6 +138,8 @@ export default defineComponent({
115
138
 
116
139
  const font = computed((): string => props.modelValue ? "text-button" : "text-body");
117
140
 
141
+ const messages = computed((): string[] => props.messages ?? getMessages(props.modelValue, props.rules));
142
+
118
143
  const onToggle = (): void => {
119
144
  if (!props.editable) {
120
145
  return;
@@ -123,6 +148,9 @@ export default defineComponent({
123
148
  }
124
149
 
125
150
  return {
151
+ validateOn,
152
+ messages,
153
+ blurred,
126
154
  style,
127
155
  font,
128
156
  onToggle
@@ -383,7 +383,12 @@ export default defineComponent({
383
383
  editor.registerUpdateListener(({ editorState }) => {
384
384
  editorState.read(() => {
385
385
  updateToolbar();
386
- emit("update:modelValue", JSON.stringify(editorState.toJSON()));
386
+ if (JSON.stringify(editorState.toJSON()) !== emptyState) {
387
+ emit("update:modelValue", JSON.stringify(editorState.toJSON()));
388
+ }
389
+ else {
390
+ emit("update:modelValue", null);
391
+ }
387
392
  });
388
393
  });
389
394
 
@@ -541,13 +546,13 @@ export default defineComponent({
541
546
  }
542
547
 
543
548
  watch(() => props.modelValue, () => {
544
- if (props.modelValue != JSON.stringify(editor.getEditorState().toJSON())) {
549
+ if (JSON.stringify(editor.getEditorState().toJSON()) != props.modelValue) {
545
550
  if (props.modelValue != null) {
546
551
  editor.update(() => {
547
552
  editor.setEditorState(editor.parseEditorState(props.modelValue));
548
553
  });
549
554
  }
550
- else {
555
+ else if (JSON.stringify(editor.getEditorState().toJSON()) !== emptyState) {
551
556
  editor.update(() => {
552
557
  editor.setEditorState(editor.parseEditorState(emptyState));
553
558
  });
@@ -0,0 +1,131 @@
1
+ <template>
2
+ <FSRow
3
+ gap="32px"
4
+ >
5
+ <FSRow
6
+ v-for="(gridItem, index) in gridItems"
7
+ :width="width"
8
+ :style="style"
9
+ :key="index"
10
+ >
11
+ <FSCol
12
+ gap="16px"
13
+ >
14
+ <FSText
15
+ font="text-h3"
16
+ >
17
+ {{ gridItem.categoryLabel }}
18
+ </FSText>
19
+ <FSCol
20
+ gap="0"
21
+ >
22
+ <FSRow
23
+ v-for="(item, index) in gridItem.items"
24
+ padding="0 8px"
25
+ align="center-center"
26
+ class="fs-grid-item"
27
+ height="hug"
28
+ :key="index"
29
+ >
30
+ <FSCol
31
+ gap="2px"
32
+ >
33
+ <slot :name="`item-header.${gridItem.categoryCode}-${item.code}`" v-bind="{ item }">
34
+ <FSText
35
+ :font="item.hideDefault ? 'text-body' : 'text-overline'"
36
+ >
37
+ {{ item.label }}
38
+ </FSText>
39
+ </slot>
40
+ <FSRow
41
+ v-if="!item.hideDefault"
42
+ >
43
+ <slot
44
+ :name="`item-value-left.${gridItem.categoryCode}-${item.code}`"
45
+ v-bind="{ item }"
46
+ >
47
+ <FSText>
48
+ {{ item.value }}
49
+ </FSText>
50
+ </slot>
51
+ </FSRow>
52
+ </FSCol>
53
+ <v-spacer />
54
+ <FSRow
55
+ v-if="useSlot(`item-value-right.${gridItem.categoryCode}-${item.code}`)"
56
+ align="center-right"
57
+ >
58
+ <slot
59
+ :name="`item-value-right.${gridItem.categoryCode}-${item.code}`"
60
+ v-bind="{ item }"
61
+ >
62
+ <FSText
63
+ font="text-body"
64
+ >
65
+ {{ item.value }}
66
+ </FSText>
67
+ </slot>
68
+ </FSRow>
69
+ </FSRow>
70
+ </FSCol>
71
+ </FSCol>
72
+ </FSRow>
73
+ </FSRow>
74
+ </template>
75
+
76
+ <script lang="ts">
77
+ import { computed, defineComponent, PropType } from "vue";
78
+
79
+ import { useBreakpoints, useColors, useSlots } from "@dative-gpi/foundation-shared-components/composables";
80
+ import { ColorEnum, GridItem } from "@dative-gpi/foundation-shared-components/models";
81
+
82
+ import FSDivider from "../FSDivider.vue";
83
+ import FSText from "../FSText.vue";
84
+
85
+ export default defineComponent({
86
+ name: "FSGrid",
87
+ components: {
88
+ FSDivider,
89
+ FSText
90
+ },
91
+ props: {
92
+ gridItems: {
93
+ type: Array as PropType<GridItem[]>,
94
+ default: [],
95
+ required: false
96
+ },
97
+ cols: {
98
+ type: Number as PropType<1 | 2>,
99
+ required: false,
100
+ default: 1
101
+ }
102
+ },
103
+ setup(props) {
104
+ const { isExtraSmall } = useBreakpoints();
105
+ const { getColors } = useColors();
106
+ const { slots } = useSlots();
107
+
108
+ const lights = getColors(ColorEnum.Light);
109
+
110
+ const style = computed((): {[code: string]: string} & Partial<CSSStyleDeclaration> => {
111
+ return {
112
+ "--fs-grid-border-color": lights.dark
113
+ };
114
+ });
115
+
116
+ const width = computed(() => {
117
+ return props.cols == 2 && !isExtraSmall.value ? "calc(50% - 16px)" : "100%";
118
+ });
119
+
120
+ const useSlot = (name: string): boolean => {
121
+ return !!slots[name];
122
+ };
123
+
124
+ return {
125
+ width,
126
+ style,
127
+ useSlot
128
+ }
129
+ }
130
+ })
131
+ </script>
@@ -0,0 +1,12 @@
1
+ export interface GridItem {
2
+ categoryLabel: string;
3
+ categoryCode: string;
4
+ items: Item[];
5
+ }
6
+
7
+ export interface Item {
8
+ label: string;
9
+ code: string;
10
+ value: string;
11
+ hideDefault: boolean;
12
+ }
package/models/index.ts CHANGED
@@ -4,6 +4,7 @@ export * from "./deviceAlerts";
4
4
  export * from "./deviceConnectivities";
5
5
  export * from "./deviceStatuses";
6
6
  export * from "./errors";
7
+ export * from "./grids";
7
8
  export * from "./modelStatuses";
8
9
  export * from "./rules";
9
10
  export * from "./tables";
package/models/rules.ts CHANGED
@@ -58,4 +58,8 @@ export const TimeRules = {
58
58
  required: (message: string) => (value: number) => !!value || (message ?? $tr("ui.rules.required", "Required")),
59
59
  min: (min: number, message: string) => (value: number) => value >= min || (message ?? $tr("ui.rules.time-min", "Must be more than {0}", getTimeBestString(min))),
60
60
  max: (max: number, message: string) => (value: number) => value <= max || (message ?? $tr("ui.rules.time-max", "Must be less than {0}", getTimeBestString(max)))
61
- };
61
+ };
62
+
63
+ export const ToggleRules = {
64
+ required: (message: string) => (value: boolean) => value || (message ?? $tr("ui.rules.required", "Required"))
65
+ }
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.45",
4
+ "version": "0.0.46",
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.45",
14
- "@dative-gpi/foundation-shared-services": "0.0.45",
13
+ "@dative-gpi/foundation-shared-domain": "0.0.46",
14
+ "@dative-gpi/foundation-shared-services": "0.0.46",
15
15
  "@fontsource/montserrat": "^5.0.16",
16
16
  "@lexical/clipboard": "^0.12.5",
17
17
  "@lexical/history": "^0.12.5",
@@ -32,5 +32,5 @@
32
32
  "sass": "^1.69.5",
33
33
  "sass-loader": "^13.3.2"
34
34
  },
35
- "gitHead": "4af778193801da465615d1718cc5562e3297d651"
35
+ "gitHead": "a1963363ed2f74aa24319fae34baeaa4d54e5e97"
36
36
  }
@@ -0,0 +1,4 @@
1
+ .fs-grid-item {
2
+ border-bottom: 1px solid var(--fs-grid-border-color);
3
+ min-height: 56px;
4
+ }
@@ -24,6 +24,7 @@
24
24
  @import "fs_fade_out.scss";
25
25
  @import "fs_filter_button.scss";
26
26
  @import "fs_form.scss";
27
+ @import "fs_grid.scss";
27
28
  @import "fs_header_button.scss";
28
29
  @import "fs_hidden_button.scss";
29
30
  @import "fs_icon_field.scss";
@@ -3,9 +3,27 @@
3
3
  display: none;
4
4
  }
5
5
 
6
- // No default hover effect on switches and others
7
- .v-selection-control__input::before {
8
- display: none;
6
+ // No default hover effect on switches and others, no limited opacity, no limited width...
7
+ .v-selection-control {
8
+ min-height: 0 !important;
9
+ }
10
+
11
+ .v-selection-control__wrapper {
12
+ height: auto !important;
13
+ width: auto !important;
14
+ }
15
+
16
+ .v-selection-control__input {
17
+ height: auto !important;
18
+ width: auto !important;
19
+
20
+ & > .v-icon {
21
+ opacity: 1 !important;
22
+ }
23
+
24
+ &::before {
25
+ display: none;
26
+ }
9
27
  }
10
28
 
11
29
  // Applies to all inputs
@@ -64,6 +82,10 @@
64
82
  }
65
83
  }
66
84
 
85
+ // No input messages allowed
86
+ .v-input__details {
87
+ display: none !important;
88
+ }
67
89
 
68
90
  // No up / down buttons in input field of type number
69
91
  input[type=number] {