@dative-gpi/foundation-shared-components 1.1.3-groupings → 1.1.3-sandbox-1

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.
@@ -13,7 +13,7 @@
13
13
  <slot />
14
14
  </FSWrapGroup>
15
15
  <FSSlideGroup
16
- v-else-if="$props.variant === 'slide'"
16
+ v-if="$props.variant === 'slide'"
17
17
  v-bind="$attrs"
18
18
  >
19
19
  <FSChip
@@ -25,103 +25,23 @@
25
25
  />
26
26
  <slot />
27
27
  </FSSlideGroup>
28
- <FSRow
29
- v-else-if="$props.variant === 'menu'"
30
- align="center-left"
31
- width="hug"
32
- :wrap="false"
33
- v-bind="$attrs"
34
- >
35
- <component
36
- v-if="hasSlots"
37
- :is="slotElements[0]"
38
- />
39
- <FSChip
40
- v-else
41
- :variant="$props.chipVariant"
42
- :color="$props.color"
43
- :label="menuLabels[0]"
44
- />
45
- <FSMenu
46
- v-if="slotElements.length > 1 || menuLabels.length > 1"
47
- location="bottom end"
48
- v-model="menuOpen"
49
- >
50
- <template
51
- #activator="{ props: activatorProps }"
52
- >
53
- <FSChip
54
- v-bind="activatorProps"
55
- variant="full"
56
- :label="`+${hasSlots ? (slotElements.length - 1) : (menuLabels.length - 1)}`"
57
- :color="menuActivatorColor"
58
- :clickable="true"
59
- />
60
- </template>
61
- <FSCard
62
- padding="16px 24px"
63
- >
64
- <FSButton
65
- style="position: absolute;top:3px;right:3px;"
66
- icon="mdi-close"
67
- variant="icon"
68
- iconSize="18px"
69
- :color="ColorEnum.Dark"
70
- @click="menuOpen = false"
71
- />
72
- <FSCol
73
- v-if="hasSlots"
74
- gap="12px"
75
- >
76
- <component
77
- v-for="(element, index) in slotElements.slice(1)"
78
- :key="index"
79
- :is="element"
80
- />
81
- </FSCol>
82
- <FSCol
83
- v-else
84
- gap="12px"
85
- >
86
- <FSChip
87
- v-for="(label, index) in menuLabels"
88
- :key="index"
89
- :variant="$props.chipVariant"
90
- :color="$props.color"
91
- :label="label"
92
- />
93
- </FSCol>
94
- </FSCard>
95
- </FSMenu>
96
- </FSRow>
97
28
  </template>
98
29
 
99
30
  <script lang="ts">
100
- import { defineComponent, ref, type PropType, useSlots, computed, type VNode } from "vue";
31
+ import { defineComponent, type PropType } from "vue";
101
32
 
102
33
  import { type CardVariant, CardVariants, type ColorBase, ColorEnum } from "@dative-gpi/foundation-shared-components/models";
103
34
 
104
35
  import FSSlideGroup from "./FSSlideGroup.vue";
105
36
  import FSWrapGroup from "./FSWrapGroup.vue";
106
- import FSButton from "./FSButton.vue";
107
37
  import FSChip from "./FSChip.vue";
108
- import FSCard from "./FSCard.vue";
109
- import FSMenu from "./FSMenu.vue";
110
- import FSCol from "./FSCol.vue";
111
- import FSRow from "./FSRow.vue";
112
- import { useColors } from "../composables";
113
38
 
114
39
  export default defineComponent({
115
40
  name: "FSChipGroup",
116
41
  components: {
117
42
  FSSlideGroup,
118
43
  FSWrapGroup,
119
- FSButton,
120
- FSChip,
121
- FSCard,
122
- FSMenu,
123
- FSCol,
124
- FSRow
44
+ FSChip
125
45
  },
126
46
  props: {
127
47
  labels: {
@@ -130,7 +50,7 @@ export default defineComponent({
130
50
  default: () => []
131
51
  },
132
52
  variant: {
133
- type: String as PropType<"wrap" | "slide" | "menu">,
53
+ type: String as PropType<"wrap" | "slide">,
134
54
  required: false,
135
55
  default: "wrap"
136
56
  },
@@ -144,45 +64,6 @@ export default defineComponent({
144
64
  required: false,
145
65
  default: ColorEnum.Light
146
66
  }
147
- },
148
- setup(props) {
149
- const slots = useSlots();
150
- const { getColors } = useColors();
151
- const menuOpen = ref(false);
152
-
153
- const slotElements = computed((): VNode[] => {
154
- const defaultSlot = slots.default?.();
155
- if (!defaultSlot) {
156
- return [];
157
- }
158
- return defaultSlot.flatMap(node => {
159
- if (node.type === Symbol.for('v-fgt')) {
160
- return (node.children as VNode[]) ?? [];
161
- }
162
- return [node];
163
- }).filter(node => typeof node.type !== 'symbol');
164
- });
165
-
166
- const hasSlots = computed((): boolean => {
167
- return slotElements.value.length > 0;
168
- });
169
-
170
- const menuLabels = computed((): string[] => {
171
- return props.labels ?? [];
172
- });
173
-
174
- const menuActivatorColor = computed((): string => {
175
- return getColors(props.color).dark;
176
- });
177
-
178
- return {
179
- menuActivatorColor,
180
- slotElements,
181
- menuLabels,
182
- ColorEnum,
183
- hasSlots,
184
- menuOpen
185
- };
186
67
  }
187
68
  });
188
69
  </script>
@@ -48,26 +48,30 @@ export default {
48
48
  to: {
49
49
  type: Object as PropType<RouteLocation | null>,
50
50
  required: false
51
+ },
52
+ html: {
53
+ type: [String, HTMLElement] as PropType<string | HTMLElement>,
54
+ required: false
51
55
  }
52
56
  },
53
57
  emits: ['click', 'auxclick'],
54
58
  setup(props, { emit }) {
55
59
  const map = inject<Ref<Map | null>>(MAP);
56
60
  const markerClusterGroup = inject<Ref<MarkerClusterGroup | null>>(MARKERCLUSTERGROUP, ref(null));
57
-
61
+
58
62
  const { getColors } = useColors();
59
63
  const { handleRoutingEvent } = useRouting();
60
64
 
61
- if(!map) {
65
+ if (!map) {
62
66
  throw new Error('FSMapTileLayer must be used inside a FSMap component');
63
67
  }
64
68
 
65
- if(!map.value) {
69
+ if (!map.value) {
66
70
  throw new Error('FSMapTileLayer must be used inside a FSMap component with a map');
67
71
  }
68
-
72
+
69
73
  const getMarkerIcon = () => {
70
- if(props.variant === 'gps') {
74
+ if (props.variant === 'gps') {
71
75
  const size = 16;
72
76
  return divIcon({
73
77
  html: gpsMarkerHtml(),
@@ -77,7 +81,7 @@ export default {
77
81
  });
78
82
  }
79
83
 
80
- if(props.variant === 'location') {
84
+ if (props.variant === 'location') {
81
85
  const size = 36;
82
86
  return divIcon({
83
87
  html: locationMarkerHtml(props.icon ?? "mdi-map-marker", getColors(props.color).base, props.label),
@@ -89,7 +93,7 @@ export default {
89
93
 
90
94
  const size = 16;
91
95
  return divIcon({
92
- html: pinMarkerHtml(getColors(props.color).base, props.label),
96
+ html: props.html ?? pinMarkerHtml(getColors(props.color).base, props.label),
93
97
  iconSize: [size, size],
94
98
  className: props.selected ? 'fs-map-marker fs-map-pin fs-map-pin-selected' : 'fs-map-marker fs-map-pin',
95
99
  iconAnchor: [size / 2, size / 2],
@@ -103,11 +107,11 @@ export default {
103
107
  });
104
108
 
105
109
  const onClick = (event: MouseEvent) => {
106
- if(props.to) {
110
+ if (props.to) {
107
111
  handleRoutingEvent(event, props.to, true);
108
112
  return;
109
113
  }
110
-
114
+
111
115
  emit('click', {
112
116
  ...event,
113
117
  latlng: props.latlng
@@ -115,7 +119,7 @@ export default {
115
119
  }
116
120
 
117
121
  const onAuxClick = (event: MouseEvent) => {
118
- if(props.to) {
122
+ if (props.to) {
119
123
  handleRoutingEvent(event, props.to);
120
124
  return;
121
125
  }
@@ -127,19 +131,19 @@ export default {
127
131
  }
128
132
 
129
133
  watch(map, () => {
130
- if(!map.value) {
134
+ if (!map.value) {
131
135
  return;
132
136
  }
133
137
 
134
- if(markerClusterGroup && markerClusterGroup.value) {
138
+ if (markerClusterGroup && markerClusterGroup.value) {
135
139
  actualMarker.value.addTo(markerClusterGroup.value);
136
140
  } else {
137
141
  actualMarker.value.addTo(map.value);
138
142
  }
139
143
  }, { immediate: true });
140
144
 
141
- watch([() => props.variant, () => props.color, () => props.selected], () => {
142
- if(!actualMarker.value || !map.value) {
145
+ watch([() => props.variant, () => props.color, () => props.selected, () => props.html], () => {
146
+ if (!actualMarker.value || !map.value) {
143
147
  return;
144
148
  }
145
149
 
@@ -148,7 +152,7 @@ export default {
148
152
  });
149
153
 
150
154
  watch([() => props.latlng?.lat, () => props.latlng?.lng], () => {
151
- if(!actualMarker.value || !map.value || !props.latlng) {
155
+ if (!actualMarker.value || !map.value || !props.latlng) {
152
156
  return;
153
157
  }
154
158
 
@@ -156,7 +160,7 @@ export default {
156
160
  });
157
161
 
158
162
  watch(markerElement, (newMarkerElement) => {
159
- if(!newMarkerElement) {
163
+ if (!newMarkerElement) {
160
164
  return;
161
165
  }
162
166
 
@@ -165,8 +169,8 @@ export default {
165
169
  }, { immediate: true });
166
170
 
167
171
  onUnmounted(() => {
168
- if(actualMarker.value && map.value) {
169
- if(markerClusterGroup && markerClusterGroup.value) {
172
+ if (actualMarker.value && map.value) {
173
+ if (markerClusterGroup && markerClusterGroup.value) {
170
174
  markerClusterGroup.value.removeLayer(actualMarker.value as Marker);
171
175
  } else {
172
176
  map.value.removeLayer(actualMarker.value as Marker);
@@ -5,8 +5,10 @@ export * from "./useBreakpoints";
5
5
  export * from "./useColors";
6
6
  export * from "./useCountUp";
7
7
  export * from "./useDebounce";
8
+ export * from "./useDynamicVNode";
8
9
  export * from "./useElementVisibility";
9
10
  export * from "./useMapLayers";
11
+ export * from "./useResize";
10
12
  export * from "./useRules";
11
13
  export * from "./useSlots";
12
14
  export * from "./useTables";
@@ -0,0 +1,62 @@
1
+ import { h, render, getCurrentInstance, onBeforeUnmount, type Component, type VNode } from "vue";
2
+
3
+ export function useDynamicVNode<TProps extends Record<string, any>>(component: Component<TProps>) {
4
+
5
+ let vnode: VNode | null = null;
6
+ let container: HTMLElement | null = null;
7
+ let mountPoint: HTMLElement | null = null;
8
+
9
+ const instance = getCurrentInstance();
10
+ if (!instance) {
11
+ throw new Error("useDynamicVNode must be used inside setup()");
12
+ }
13
+
14
+ const appContext = instance.appContext;
15
+
16
+ const mount = async (props: TProps) => {
17
+ if (!mountPoint) {
18
+ throw new Error(`You must call getElement() first to create the mount point`);
19
+ }
20
+
21
+ if (!container) {
22
+ container = document.createElement("div");
23
+ mountPoint.appendChild(container);
24
+ }
25
+
26
+ vnode = h(component, props);
27
+ vnode.appContext = appContext;
28
+
29
+ render(vnode, container);
30
+ };
31
+
32
+ const unmount = () => {
33
+ if (container) {
34
+ render(null, container);
35
+ container.remove();
36
+ }
37
+ vnode = null;
38
+ container = null;
39
+ };
40
+
41
+ const getElement = (style?: Partial<CSSStyleDeclaration>): HTMLElement => {
42
+ if (!mountPoint) {
43
+ mountPoint = document.createElement("div");
44
+ }
45
+ mountPoint = document.createElement("div");
46
+ Object.assign(mountPoint.style, style ?? {});
47
+ return mountPoint;
48
+ };
49
+
50
+ const destroy = () => {
51
+ unmount();
52
+ mountPoint = null;
53
+ };
54
+
55
+ onBeforeUnmount(destroy);
56
+
57
+ return {
58
+ mount,
59
+ unmount,
60
+ getElement
61
+ };
62
+ }
@@ -0,0 +1,32 @@
1
+ import { onMounted, onBeforeUnmount } from 'vue';
2
+
3
+ export function useResize(
4
+ getElement: () => HTMLElement | null | undefined,
5
+ onResize: () => void
6
+ ) {
7
+ let resizeObserver: ResizeObserver | null = null;
8
+
9
+ onMounted(() => {
10
+ if (typeof ResizeObserver !== 'undefined') {
11
+ resizeObserver = new ResizeObserver(() => {
12
+ onResize();
13
+ });
14
+ const element = getElement();
15
+ if (element) {
16
+ resizeObserver.observe(element);
17
+ }
18
+ }
19
+
20
+ window.addEventListener('resize', onResize);
21
+ });
22
+
23
+ onBeforeUnmount(() => {
24
+ window.removeEventListener('resize', onResize);
25
+ resizeObserver?.disconnect();
26
+ resizeObserver = null;
27
+ });
28
+
29
+ return {
30
+ resize: onResize
31
+ };
32
+ }
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "url": "https://github.com/Dative-GPI/foundation-shared-ui.git"
5
5
  },
6
6
  "sideEffects": false,
7
- "version": "1.1.3-groupings",
7
+ "version": "1.1.3-sandbox-1",
8
8
  "description": "",
9
9
  "publishConfig": {
10
10
  "access": "public"
@@ -13,8 +13,8 @@
13
13
  "author": "",
14
14
  "license": "ISC",
15
15
  "dependencies": {
16
- "@dative-gpi/foundation-shared-domain": "1.1.3-groupings",
17
- "@dative-gpi/foundation-shared-services": "1.1.3-groupings"
16
+ "@dative-gpi/foundation-shared-domain": "1.1.3-sandbox-1",
17
+ "@dative-gpi/foundation-shared-services": "1.1.3-sandbox-1"
18
18
  },
19
19
  "peerDependencies": {
20
20
  "@dative-gpi/bones-ui": "^1.0.0",
@@ -38,5 +38,5 @@
38
38
  "sass": "1.71.1",
39
39
  "sass-loader": "13.3.2"
40
40
  },
41
- "gitHead": "ad40c30f9ecd5b50de62619fa3cfab64e63d7cc5"
41
+ "gitHead": "8857dc338d7d3ec5f09ce9f67b0b359ae25e8e40"
42
42
  }
@@ -1,110 +0,0 @@
1
- <template>
2
- <FSChip
3
- :height="$props.height"
4
- :width="$props.width"
5
- :variant="$props.variant"
6
- :color="borderColor"
7
- >
8
- <FSRow
9
- align="center-center"
10
- width="hug"
11
- :wrap="false"
12
- >
13
- <FSRow
14
- align="center-center"
15
- width="hug"
16
- gap="6px"
17
- :wrap="false"
18
- >
19
- <FSIcon
20
- :color="$props.iconColor"
21
- :size="$props.iconSize"
22
- >
23
- {{ $props.icon }}
24
- </FSIcon>
25
- <FSText
26
- font="text-overline"
27
- :color="textColor"
28
- >
29
- {{ $props.label }}
30
- </FSText>
31
- </FSRow>
32
- </FSRow>
33
- </FSChip>
34
- </template>
35
-
36
- <script lang="ts">
37
- import { defineComponent, type PropType } from "vue";
38
-
39
- import { type ColorBase, ColorEnum } from "@dative-gpi/foundation-shared-components/models";
40
-
41
- import FSIcon from "./FSIcon.vue";
42
- import FSText from "./FSText.vue";
43
- import FSChip from "./FSChip.vue";
44
- import FSRow from "./FSRow.vue";
45
-
46
- import { useColors } from "../composables";
47
-
48
- export default defineComponent({
49
- name: "FSSubgroupingChip",
50
- components: {
51
- FSChip,
52
- FSIcon,
53
- FSText,
54
- FSRow
55
- },
56
- inheritAttrs: false,
57
- props: {
58
- label: {
59
- type: String as PropType<string>,
60
- required: true
61
- },
62
- icon: {
63
- type: String as PropType<string>,
64
- required: true
65
- },
66
- iconColor: {
67
- type: String as PropType<ColorBase>,
68
- required: false,
69
- default: ColorEnum.Dark
70
- },
71
- height: {
72
- type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
73
- required: false,
74
- default: () => [24, 20]
75
- },
76
- width: {
77
- type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
78
- required: false,
79
- default: "hug"
80
- },
81
- color: {
82
- type: String as PropType<ColorBase>,
83
- required: false,
84
- default: ColorEnum.Light
85
- },
86
- variant: {
87
- type: String as PropType<"standard" | "full" | "borderless">,
88
- required: false,
89
- default: "standard"
90
- },
91
- iconSize: {
92
- type: [Array, String, Number] as PropType<"s" | "m" | "l" | string[] | number[] | string | number | null>,
93
- required: false,
94
- default: "18px"
95
- }
96
- },
97
- setup(props) {
98
- const { getColors } = useColors();
99
-
100
- const borderColor = getColors(props.color).dark;
101
- const textColor = getColors(ColorEnum.Dark).dark;
102
-
103
- return {
104
- borderColor,
105
- textColor,
106
- ColorEnum
107
- };
108
- }
109
- });
110
- </script>
@@ -1,135 +0,0 @@
1
- <template>
2
- <FSChip
3
- :height="$props.height"
4
- :width="$props.width"
5
- :variant="$props.variant"
6
- :color="borderColor"
7
- >
8
- <FSRow
9
- align="center-center"
10
- width="hug"
11
- :wrap="false"
12
- >
13
- <FSRow
14
- align="center-center"
15
- width="hug"
16
- gap="6px"
17
- :wrap="false"
18
- >
19
- <FSIcon
20
- :color="$props.groupingColor"
21
- :size="$props.iconSize"
22
- >
23
- {{ $props.groupingIcon }}
24
- </FSIcon>
25
- <FSText
26
- font="text-overline"
27
- :color="textColor"
28
- >
29
- {{ $props.groupingLabel }}
30
- </FSText>
31
- </FSRow>
32
- <FSRow
33
- align="center-center"
34
- width="hug"
35
- gap="6px"
36
- :wrap="false"
37
- >
38
- <FSIcon
39
- :size="$props.iconSize"
40
- :color="textColor"
41
- >
42
- {{ $props.icon }}
43
- </FSIcon>
44
- <FSText
45
- font="text-overline"
46
- :color="textColor"
47
- >
48
- {{ $props.label }}
49
- </FSText>
50
- </FSRow>
51
- </FSRow>
52
- </FSChip>
53
- </template>
54
-
55
- <script lang="ts">
56
- import { defineComponent, type PropType } from "vue";
57
-
58
- import { type ColorBase, ColorEnum } from "@dative-gpi/foundation-shared-components/models";
59
-
60
- import FSIcon from "./FSIcon.vue";
61
- import FSText from "./FSText.vue";
62
- import FSChip from "./FSChip.vue";
63
- import FSRow from "./FSRow.vue";
64
- import { useColors } from "../composables";
65
-
66
- export default defineComponent({
67
- name: "FSSubgroupingChip",
68
- components: {
69
- FSChip,
70
- FSIcon,
71
- FSText,
72
- FSRow
73
- },
74
- props: {
75
- groupingLabel: {
76
- type: String as PropType<string>,
77
- required: true
78
- },
79
- groupingIcon: {
80
- type: String as PropType<string>,
81
- required: true
82
- },
83
- groupingColor: {
84
- type: String as PropType<ColorBase>,
85
- required: false,
86
- default: ColorEnum.Dark
87
- },
88
- label: {
89
- type: String as PropType<string>,
90
- required: true
91
- },
92
- icon: {
93
- type: String as PropType<string>,
94
- required: true
95
- },
96
- height: {
97
- type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
98
- required: false,
99
- default: () => [24, 20]
100
- },
101
- width: {
102
- type: [Array, String, Number] as PropType<string[] | number[] | string | number | null>,
103
- required: false,
104
- default: "hug"
105
- },
106
- variant: {
107
- type: String as PropType<"standard" | "full" | "borderless">,
108
- required: false,
109
- default: "standard"
110
- },
111
- color: {
112
- type: String as PropType<ColorBase>,
113
- required: false,
114
- default: ColorEnum.Light
115
- },
116
- iconSize: {
117
- type: [Array, String, Number] as PropType<"s" | "m" | "l" | string[] | number[] | string | number | null>,
118
- required: false,
119
- default: "18px"
120
- }
121
- },
122
- setup(props) {
123
- const { getColors } = useColors();
124
-
125
- const borderColor = getColors(props.color).dark;
126
- const textColor = getColors(ColorEnum.Dark).dark;
127
-
128
- return {
129
- borderColor,
130
- textColor,
131
- ColorEnum
132
- };
133
- }
134
- });
135
- </script>
@@ -1,45 +0,0 @@
1
- <template>
2
- <FSSimpleTileUI
3
- :bottomColor="null"
4
- v-bind="$attrs"
5
- >
6
- <template
7
- #append-info
8
- >
9
- <FSEntityCountBadge
10
- :label="$tr('ui.common.equipments', 'Équipements')"
11
- :count="$props.deviceOrganisationsCount ?? 0"
12
- :color="ColorEnum.Primary"
13
- />
14
- </template>
15
- </FSSimpleTileUI>
16
- </template>
17
-
18
- <script lang="ts">
19
- import { defineComponent } from "vue";
20
-
21
- import { ColorEnum } from "@dative-gpi/foundation-shared-components/models";
22
-
23
- import FSEntityCountBadge from "./FSEntityCountBadge.vue";
24
- import FSSimpleTileUI from './FSSimpleTileUI.vue';
25
-
26
- export default defineComponent({
27
- name: "FSSubgroupingTileUI",
28
- components: {
29
- FSSimpleTileUI,
30
- FSEntityCountBadge
31
- },
32
- props: {
33
- deviceOrganisationsCount: {
34
- type: Number,
35
- required: false,
36
- default: null
37
- }
38
- },
39
- setup() {
40
- return {
41
- ColorEnum,
42
- };
43
- }
44
- });
45
- </script>