@fmidev/smartmet-alert-client 4.4.19 → 4.7.0-beta.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.
Files changed (123) hide show
  1. package/.eslintignore +2 -14
  2. package/.github/workflows/test.yaml +26 -0
  3. package/.nvmrc +1 -0
  4. package/AGENTS.md +26 -0
  5. package/index.html +1 -1
  6. package/package.json +80 -22
  7. package/src/AlertClientVue.vue +160 -0
  8. package/src/App.vue +154 -296
  9. package/src/assets/img/ui/arrow-down.svg +4 -11
  10. package/src/assets/img/ui/arrow-up.svg +4 -11
  11. package/src/assets/img/ui/clear.svg +7 -21
  12. package/src/assets/img/ui/close.svg +4 -15
  13. package/src/assets/img/ui/toggle-selected.svg +5 -6
  14. package/src/assets/img/ui/toggle-unselected.svg +5 -6
  15. package/src/assets/img/warning/cold-weather.svg +3 -6
  16. package/src/assets/img/warning/flood-level-3.svg +4 -7
  17. package/src/assets/img/warning/forest-fire-weather.svg +2 -6
  18. package/src/assets/img/warning/grass-fire-weather.svg +2 -6
  19. package/src/assets/img/warning/hot-weather.svg +3 -6
  20. package/src/assets/img/warning/pedestrian-safety.svg +3 -7
  21. package/src/assets/img/warning/rain.svg +2 -7
  22. package/src/assets/img/warning/sea-icing.svg +2 -6
  23. package/src/assets/img/warning/sea-thunder-storm.svg +2 -5
  24. package/src/assets/img/warning/sea-water-height-high-water.svg +3 -8
  25. package/src/assets/img/warning/sea-water-height-shallow-water.svg +3 -7
  26. package/src/assets/img/warning/sea-wave-height.svg +4 -7
  27. package/src/assets/img/warning/sea-wind-legend.svg +2 -5
  28. package/src/assets/img/warning/sea-wind.svg +2 -5
  29. package/src/assets/img/warning/several.svg +2 -5
  30. package/src/assets/img/warning/thunder-storm.svg +2 -5
  31. package/src/assets/img/warning/traffic-weather.svg +2 -6
  32. package/src/assets/img/warning/uv-note.svg +2 -6
  33. package/src/assets/img/warning/wind.svg +2 -5
  34. package/src/components/AlertClient.vue +330 -251
  35. package/src/components/CollapsiblePanel.vue +281 -0
  36. package/src/components/DayLarge.vue +146 -110
  37. package/src/components/DaySmall.vue +97 -81
  38. package/src/components/Days.vue +229 -159
  39. package/src/components/DescriptionWarning.vue +63 -38
  40. package/src/components/GrayScaleToggle.vue +58 -54
  41. package/src/components/Legend.vue +102 -325
  42. package/src/components/MapLarge.vue +574 -351
  43. package/src/components/MapSmall.vue +137 -122
  44. package/src/components/PopupRow.vue +24 -12
  45. package/src/components/Region.vue +168 -118
  46. package/src/components/RegionWarning.vue +40 -33
  47. package/src/components/Regions.vue +189 -105
  48. package/src/components/Warning.vue +70 -45
  49. package/src/components/Warnings.vue +136 -72
  50. package/src/composables/useAlertClient.ts +360 -0
  51. package/src/composables/useConfig.ts +573 -0
  52. package/src/composables/useFields.ts +66 -0
  53. package/src/composables/useI18n.ts +62 -0
  54. package/src/composables/useKeyCodes.ts +16 -0
  55. package/src/composables/useMapPaths.ts +477 -0
  56. package/src/composables/useUtils.ts +683 -0
  57. package/src/composables/useWarningsProcessor.ts +1007 -0
  58. package/src/data/geometries.json +993 -0
  59. package/src/{main.js → main.ts} +1 -0
  60. package/src/mixins/geojsonsvg.d.ts +57 -0
  61. package/src/mixins/geojsonsvg.js +5 -3
  62. package/src/plugins/index.ts +5 -0
  63. package/src/scss/_utilities.scss +193 -0
  64. package/src/scss/constants.scss +2 -1
  65. package/src/scss/warningImages.scss +8 -3
  66. package/src/types/index.ts +509 -0
  67. package/src/vite-env.d.ts +23 -0
  68. package/src/vue.ts +41 -0
  69. package/svgo.config.js +45 -0
  70. package/tests/README.md +430 -0
  71. package/tests/fixtures/mockWarningData.ts +152 -0
  72. package/tests/integration/warning-flow.spec.ts +445 -0
  73. package/tests/setup.ts +41 -0
  74. package/tests/unit/components/AlertClient.spec.ts +701 -0
  75. package/tests/unit/components/DayLarge.spec.ts +348 -0
  76. package/tests/unit/components/DaySmall.spec.ts +352 -0
  77. package/tests/unit/components/Days.spec.ts +548 -0
  78. package/tests/unit/components/DescriptionWarning.spec.ts +385 -0
  79. package/tests/unit/components/GrayScaleToggle.spec.ts +318 -0
  80. package/tests/unit/components/Legend.spec.ts +295 -0
  81. package/tests/unit/components/MapLarge.spec.ts +448 -0
  82. package/tests/unit/components/MapSmall.spec.ts +367 -0
  83. package/tests/unit/components/PopupRow.spec.ts +270 -0
  84. package/tests/unit/components/Region.spec.ts +373 -0
  85. package/tests/unit/components/RegionWarning.snapshot.spec.ts +361 -0
  86. package/tests/unit/components/RegionWarning.spec.ts +381 -0
  87. package/tests/unit/components/Regions.spec.ts +503 -0
  88. package/tests/unit/components/Warning.snapshot.spec.ts +483 -0
  89. package/tests/unit/components/Warning.spec.ts +489 -0
  90. package/tests/unit/components/Warnings.spec.ts +343 -0
  91. package/tests/unit/components/__snapshots__/RegionWarning.snapshot.spec.ts.snap +41 -0
  92. package/tests/unit/components/__snapshots__/Warning.snapshot.spec.ts.snap +433 -0
  93. package/tests/unit/composables/useConfig.spec.ts +279 -0
  94. package/tests/unit/composables/useI18n.spec.ts +116 -0
  95. package/tests/unit/composables/useKeyCodes.spec.ts +27 -0
  96. package/tests/unit/composables/useUtils.spec.ts +213 -0
  97. package/tsconfig.json +43 -0
  98. package/tsconfig.node.json +11 -0
  99. package/vite.config.js +96 -26
  100. package/vitest.config.js +40 -0
  101. package/dist/favicon.ico +0 -0
  102. package/dist/index.dark.html +0 -20
  103. package/dist/index.en.html +0 -15
  104. package/dist/index.fi.html +0 -15
  105. package/dist/index.html +0 -15
  106. package/dist/index.js +0 -281
  107. package/dist/index.mjs +0 -281
  108. package/dist/index.mjs.map +0 -1
  109. package/dist/index.relative.html +0 -19
  110. package/dist/index.start.html +0 -20
  111. package/dist/index.sv.html +0 -15
  112. package/playwright.config.ts +0 -18
  113. package/public/index.relative.html +0 -19
  114. package/public/index.start.html +0 -20
  115. package/src/mixins/config.js +0 -1378
  116. package/src/mixins/fields.js +0 -26
  117. package/src/mixins/i18n.js +0 -25
  118. package/src/mixins/keycodes.js +0 -10
  119. package/src/mixins/panzoom.js +0 -900
  120. package/src/mixins/utils.js +0 -900
  121. package/src/plugins/index.js +0 -3
  122. package/test/snapshot.test.ts +0 -126
  123. package/vitest.config.ts +0 -6
@@ -5,6 +5,7 @@ import {
5
5
  h,
6
6
  } from 'vue'
7
7
  import { createWebComponent } from 'vue-web-component-wrapper'
8
+
8
9
  import app from './App.vue'
9
10
 
10
11
  createWebComponent({
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Type declarations for geojsonsvg.js mixin
3
+ *
4
+ * This mixin is adapted from mapshaper and provides GeoJSON to SVG conversion.
5
+ * The implementation remains in JavaScript for stability.
6
+ */
7
+
8
+ import type { ComponentOptionsMixin } from 'vue'
9
+
10
+ export interface GeoJSONFeature {
11
+ type: 'Feature'
12
+ id?: string
13
+ geometry: GeoJSONGeometry | null
14
+ properties: Record<string, unknown>
15
+ }
16
+
17
+ export interface GeoJSONGeometry {
18
+ type: string
19
+ coordinates?: unknown
20
+ geometries?: GeoJSONGeometry[]
21
+ }
22
+
23
+ export interface GeoJSONFeatureCollection {
24
+ type: 'FeatureCollection'
25
+ features: GeoJSONFeature[]
26
+ totalFeatures?: number
27
+ crs?: {
28
+ type: string
29
+ properties: {
30
+ name: string
31
+ }
32
+ }
33
+ }
34
+
35
+ export interface SVGExportOptions {
36
+ invert_y?: boolean
37
+ rfc7946?: boolean
38
+ v2?: boolean
39
+ width?: number
40
+ height?: number
41
+ }
42
+
43
+ declare const geojsonsvg: ComponentOptionsMixin & {
44
+ methods: {
45
+ /**
46
+ * Convert GeoJSON data to SVG string
47
+ */
48
+ geoJSONToSVG(
49
+ data: GeoJSONFeatureCollection,
50
+ width: number,
51
+ height: number,
52
+ options?: SVGExportOptions
53
+ ): string
54
+ }
55
+ }
56
+
57
+ export default geojsonsvg
@@ -2933,7 +2933,7 @@ export default {
2933
2933
  },
2934
2934
  copyDataset(dataset) {
2935
2935
  const d2 = extendUtil({}, dataset)
2936
- d2.layers = d2.layers.map(this.copyLayer)
2936
+ d2.layers = d2.layers.map((lyr) => this.copyLayer(lyr))
2937
2937
  if (d2.arcs) {
2938
2938
  d2.arcs = d2.arcs.getFilteredCopy()
2939
2939
  }
@@ -2960,7 +2960,7 @@ export default {
2960
2960
  })
2961
2961
  },
2962
2962
  cloneShapes(arr) {
2963
- return Array.isArray(arr) ? arr.map(this.cloneShape) : null
2963
+ return Array.isArray(arr) ? arr.map((shp) => this.cloneShape(shp)) : null
2964
2964
  },
2965
2965
  pluck(arr, key) {
2966
2966
  return arr.map(function (obj) {
@@ -3140,7 +3140,9 @@ export default {
3140
3140
  svg += obj.value
3141
3141
  }
3142
3142
  if (obj.children) {
3143
- svg += obj.children.map(this.stringify).join(joinStr)
3143
+ svg += obj.children
3144
+ .map((child) => this.stringify(child))
3145
+ .join(joinStr)
3144
3146
  }
3145
3147
  svg += joinStr + '</' + obj.tag + '>'
3146
3148
  } else {
@@ -0,0 +1,5 @@
1
+ import type { App } from 'vue'
2
+
3
+ export const pluginsWrapper = {
4
+ install(_app: App): void {},
5
+ }
@@ -0,0 +1,193 @@
1
+ // Responsive display utilities
2
+ .mobile-only {
3
+ display: block;
4
+ @media (min-width: 768px) {
5
+ display: none;
6
+ }
7
+ }
8
+
9
+ .desktop-only {
10
+ display: none;
11
+ @media (min-width: 768px) {
12
+ display: block;
13
+ }
14
+ }
15
+
16
+ .d-none {
17
+ display: none !important;
18
+ }
19
+
20
+ .d-block {
21
+ display: block !important;
22
+ }
23
+
24
+ // Medium breakpoint and up (768px+)
25
+ @media (min-width: 768px) {
26
+ .d-md-none {
27
+ display: none !important;
28
+ }
29
+
30
+ .d-md-block {
31
+ display: block !important;
32
+ }
33
+
34
+ .d-md-table-cell {
35
+ display: table-cell !important;
36
+ }
37
+ }
38
+
39
+ // Display inline
40
+ .d-inline {
41
+ display: inline !important;
42
+ }
43
+
44
+ // For screen readers
45
+ .visually-hidden {
46
+ position: absolute;
47
+ width: 1px;
48
+ height: 1px;
49
+ padding: 0;
50
+ margin: -1px;
51
+ overflow: hidden;
52
+ clip: rect(0, 0, 0, 0);
53
+ white-space: nowrap;
54
+ border: 0;
55
+ }
56
+
57
+ // Accessibility utilities
58
+ .visually-hidden-focusable {
59
+ position: absolute !important;
60
+ width: 1px !important;
61
+ height: 1px !important;
62
+ padding: 0 !important;
63
+ margin: -1px !important;
64
+ overflow: hidden !important;
65
+ clip: rect(0, 0, 0, 0) !important;
66
+ white-space: nowrap !important;
67
+ border: 0 !important;
68
+
69
+ &:focus,
70
+ &:focus-within {
71
+ position: static !important;
72
+ width: auto !important;
73
+ height: auto !important;
74
+ overflow: visible !important;
75
+ clip: auto !important;
76
+ white-space: normal !important;
77
+ }
78
+ }
79
+
80
+ .focus-ring {
81
+ outline: none;
82
+
83
+ &:focus {
84
+ outline: 2px solid #0d6efd;
85
+ outline-offset: 2px;
86
+ }
87
+
88
+ &:focus:not(:focus-visible) {
89
+ outline: none;
90
+ }
91
+
92
+ &:focus-visible {
93
+ outline: 2px solid #0d6efd;
94
+ outline-offset: 2px;
95
+ }
96
+ }
97
+
98
+ // Small breakpoint specific (576px+)
99
+ @media (min-width: 576px) {
100
+ .d-sm-block {
101
+ display: block !important;
102
+ }
103
+
104
+ .d-sm-none {
105
+ display: none !important;
106
+ }
107
+ }
108
+
109
+ // Spacing utilities
110
+ .mb-1 {
111
+ margin-bottom: 0.25rem;
112
+ }
113
+
114
+ .p-0 {
115
+ padding: 0;
116
+ }
117
+
118
+ .p-1 {
119
+ padding: 0.25rem;
120
+ }
121
+
122
+ // Position utilities
123
+ .sticky-top {
124
+ position: sticky;
125
+ top: 0;
126
+ z-index: 1020;
127
+ }
128
+
129
+ // Grid/Layout utilities
130
+ .row {
131
+ display: flex;
132
+ flex-wrap: wrap;
133
+ margin-left: 0;
134
+ margin-right: 0;
135
+ }
136
+
137
+ // Tab navigation utilities
138
+ .nav {
139
+ display: flex;
140
+ flex-wrap: wrap;
141
+ padding-left: 0;
142
+ margin-bottom: 0;
143
+ list-style: none;
144
+ }
145
+
146
+ .nav-tabs {
147
+ border-bottom: none;
148
+ }
149
+
150
+ .nav-item {
151
+ margin-bottom: 0;
152
+ }
153
+
154
+ .nav-link {
155
+ display: block;
156
+ padding: 0;
157
+ text-decoration: none;
158
+ background: none;
159
+ border: none;
160
+ cursor: pointer;
161
+ }
162
+
163
+ .tab-content {
164
+ > .tab-pane {
165
+ display: none;
166
+
167
+ &.active,
168
+ &.show {
169
+ display: block;
170
+ }
171
+ }
172
+
173
+ .spinner-border {
174
+ display: inline-block;
175
+ width: 2rem;
176
+ height: 2rem;
177
+ vertical-align: text-bottom;
178
+ border: 0.25em solid currentColor;
179
+ border-right-color: transparent;
180
+ border-radius: 50%;
181
+ animation: spinner-border-animation 0.75s linear infinite;
182
+ }
183
+
184
+ @keyframes spinner-border-animation {
185
+ to {
186
+ transform: rotate(360deg);
187
+ }
188
+ }
189
+
190
+ .text-center {
191
+ text-align: center !important;
192
+ }
193
+ }
@@ -35,7 +35,8 @@ $popup-width: 250px;
35
35
  font-family: 'Noto Sans';
36
36
  font-weight: normal;
37
37
  font-style: normal;
38
- src: url($font-base-path + 'Noto_Sans/Noto-Sans-regular.woff2') format('woff2');
38
+ src: url($font-base-path + 'Noto_Sans/Noto-Sans-regular.woff2')
39
+ format('woff2');
39
40
  font-display: swap;
40
41
  }
41
42
  $font-family: Roboto, Helvetica, Arial, 'Noto Sans', sans-serif;
@@ -1,8 +1,9 @@
1
- @import "./constants.scss";
1
+ @use 'sass:string';
2
+ @import './constants.scss';
2
3
 
3
4
  @for $i from 0 through 72 {
4
5
  $angle: 5 * $i;
5
- $rotationDegree: unquote($angle + 'deg');
6
+ $rotationDegree: string.unquote($angle + 'deg');
6
7
  .transform-rotate-#{$angle} {
7
8
  transform: rotate($rotationDegree);
8
9
  }
@@ -101,7 +102,11 @@ div.symbol-image {
101
102
  }
102
103
 
103
104
  @media (forced-colors: active) {
104
- .level-0, .level-1, .level-2, .level-3, .level-4 {
105
+ .level-0,
106
+ .level-1,
107
+ .level-2,
108
+ .level-3,
109
+ .level-4 {
105
110
  forced-color-adjust: none;
106
111
  }
107
112
  }