@cfasim-ui/docs 0.3.11

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 (60) hide show
  1. package/LICENSE +201 -0
  2. package/charts/ChartMenu/ChartMenu.vue +140 -0
  3. package/charts/ChartMenu/download.ts +44 -0
  4. package/charts/ChartTooltip/ChartTooltip.vue +97 -0
  5. package/charts/ChoroplethMap/ChoroplethMap.md +398 -0
  6. package/charts/ChoroplethMap/ChoroplethMap.vue +777 -0
  7. package/charts/ChoroplethMap/hsaMapping.ts +4116 -0
  8. package/charts/DataTable/DataTable.md +143 -0
  9. package/charts/DataTable/DataTable.vue +277 -0
  10. package/charts/LineChart/LineChart.md +472 -0
  11. package/charts/LineChart/LineChart.vue +1216 -0
  12. package/charts/index.ts +23 -0
  13. package/charts/tooltip-position.ts +49 -0
  14. package/components/Box/Box.md +49 -0
  15. package/components/Box/Box.vue +52 -0
  16. package/components/Button/Button.md +67 -0
  17. package/components/Button/Button.vue +81 -0
  18. package/components/Expander/Expander.md +34 -0
  19. package/components/Expander/Expander.vue +95 -0
  20. package/components/Hint/Hint.md +29 -0
  21. package/components/Hint/Hint.vue +83 -0
  22. package/components/Icon/Icon.md +67 -0
  23. package/components/Icon/Icon.vue +112 -0
  24. package/components/LightDarkToggle/LightDarkToggle.vue +49 -0
  25. package/components/NumberInput/NumberInput.md +305 -0
  26. package/components/NumberInput/NumberInput.vue +531 -0
  27. package/components/SelectBox/SelectBox.md +110 -0
  28. package/components/SelectBox/SelectBox.vue +195 -0
  29. package/components/SidebarLayout/SidebarLayout.md +104 -0
  30. package/components/SidebarLayout/SidebarLayout.vue +466 -0
  31. package/components/Spinner/Spinner.md +51 -0
  32. package/components/Spinner/Spinner.vue +55 -0
  33. package/components/TextInput/TextInput.md +82 -0
  34. package/components/TextInput/TextInput.vue +94 -0
  35. package/components/Toggle/Toggle.md +81 -0
  36. package/components/Toggle/Toggle.vue +81 -0
  37. package/components/index.ts +15 -0
  38. package/index.json +121 -0
  39. package/package.json +24 -0
  40. package/pyodide/index.ts +7 -0
  41. package/pyodide/pyodide.worker.ts +233 -0
  42. package/pyodide/pyodideWorkerApi.ts +102 -0
  43. package/pyodide/useModel.ts +86 -0
  44. package/pyodide/vitePlugin.js +51 -0
  45. package/shared/ModelOutput.ts +88 -0
  46. package/shared/csv.ts +22 -0
  47. package/shared/index.ts +24 -0
  48. package/shared/transferUtils.ts +126 -0
  49. package/shared/useUrlParams.ts +296 -0
  50. package/theme/all.js +5 -0
  51. package/theme/base.css +176 -0
  52. package/theme/cfasim.css +3 -0
  53. package/theme/theme.css +113 -0
  54. package/theme/themes/cdc.css +22 -0
  55. package/theme/utilities.css +518 -0
  56. package/wasm/index.ts +2 -0
  57. package/wasm/useModel.ts +53 -0
  58. package/wasm/vitePlugin.js +35 -0
  59. package/wasm/wasm.worker.ts +74 -0
  60. package/wasm/wasmWorkerApi.ts +38 -0
@@ -0,0 +1,112 @@
1
+ <script setup lang="ts">
2
+ import type { CSSProperties } from "vue";
3
+ import { computed } from "vue";
4
+
5
+ export type IconSize = "sm" | "md" | "lg" | "xl";
6
+
7
+ interface Props {
8
+ icon: string;
9
+ size?: IconSize | number;
10
+ fill?: boolean;
11
+ weight?: number;
12
+ grade?: number;
13
+ decorative?: boolean;
14
+ ariaLabel?: string;
15
+ inline?: boolean;
16
+ }
17
+
18
+ const props = withDefaults(defineProps<Props>(), {
19
+ size: "md",
20
+ fill: false,
21
+ decorative: true,
22
+ inline: false,
23
+ });
24
+
25
+ const sizePreset = computed(() =>
26
+ typeof props.size === "string" ? props.size : undefined,
27
+ );
28
+ const numericSize = computed(() =>
29
+ typeof props.size === "number" ? props.size : undefined,
30
+ );
31
+
32
+ const inlineStyle = computed<CSSProperties>(() => {
33
+ const style: CSSProperties = {};
34
+ if (numericSize.value !== undefined) {
35
+ style.fontSize = `${numericSize.value}px`;
36
+ (style as Record<string, unknown>)["--icon-opsz"] = numericSize.value;
37
+ }
38
+ if (props.weight !== undefined) {
39
+ (style as Record<string, unknown>)["--icon-weight"] = props.weight;
40
+ }
41
+ if (props.grade !== undefined) {
42
+ (style as Record<string, unknown>)["--icon-grade"] = props.grade;
43
+ }
44
+ return style;
45
+ });
46
+ </script>
47
+
48
+ <template>
49
+ <span
50
+ class="Icon"
51
+ :data-size="sizePreset"
52
+ :data-fill="fill ? 'true' : undefined"
53
+ :data-inline="inline ? 'true' : undefined"
54
+ :style="inlineStyle"
55
+ :aria-hidden="decorative ? true : undefined"
56
+ :aria-label="decorative ? undefined : ariaLabel"
57
+ :role="decorative ? undefined : 'img'"
58
+ >{{ icon }}</span
59
+ >
60
+ </template>
61
+
62
+ <style>
63
+ .Icon {
64
+ font-family: "Material Symbols Outlined", sans-serif;
65
+ font-weight: normal;
66
+ font-style: normal;
67
+ font-size: 24px;
68
+ line-height: 1;
69
+ letter-spacing: normal;
70
+ text-transform: none;
71
+ display: inline-block;
72
+ white-space: nowrap;
73
+ word-wrap: normal;
74
+ direction: ltr;
75
+ font-feature-settings: "liga";
76
+ -webkit-font-smoothing: antialiased;
77
+ font-variation-settings:
78
+ "FILL" var(--icon-fill, 0),
79
+ "wght" var(--icon-weight, 400),
80
+ "GRAD" var(--icon-grade, 0),
81
+ "opsz" var(--icon-opsz, 24);
82
+ color: inherit;
83
+ }
84
+
85
+ .Icon[data-size="sm"] {
86
+ font-size: 20px;
87
+ --icon-opsz: 20;
88
+ }
89
+ .Icon[data-size="md"] {
90
+ font-size: 24px;
91
+ --icon-opsz: 24;
92
+ }
93
+ .Icon[data-size="lg"] {
94
+ font-size: 28px;
95
+ --icon-opsz: 28;
96
+ }
97
+ .Icon[data-size="xl"] {
98
+ font-size: 32px;
99
+ --icon-opsz: 32;
100
+ }
101
+
102
+ .Icon[data-fill="true"] {
103
+ --icon-fill: 1;
104
+ }
105
+
106
+ .Icon[data-inline="true"] {
107
+ font-size: inherit;
108
+ vertical-align: middle;
109
+ transform: scale(1.2) translateY(-0.05em);
110
+ transform-origin: 50% 50%;
111
+ }
112
+ </style>
@@ -0,0 +1,49 @@
1
+ <script setup lang="ts">
2
+ import { ref, watch } from "vue";
3
+ import Icon from "../Icon/Icon.vue";
4
+
5
+ const isDark = ref(window.matchMedia("(prefers-color-scheme: dark)").matches);
6
+
7
+ function apply(dark: boolean) {
8
+ document.documentElement.classList.toggle("dark", dark);
9
+ document.documentElement.classList.toggle("light", !dark);
10
+ }
11
+
12
+ apply(isDark.value);
13
+
14
+ watch(isDark, apply);
15
+ </script>
16
+
17
+ <template>
18
+ <button
19
+ class="light-dark-toggle"
20
+ type="button"
21
+ :aria-label="isDark ? 'Switch to light mode' : 'Switch to dark mode'"
22
+ @click="isDark = !isDark"
23
+ >
24
+ <Icon :icon="isDark ? 'dark_mode' : 'light_mode'" size="sm" />
25
+ </button>
26
+ </template>
27
+
28
+ <style scoped>
29
+ .light-dark-toggle {
30
+ display: flex;
31
+ align-items: center;
32
+ justify-content: center;
33
+ width: 32px;
34
+ height: 32px;
35
+ border: 1px solid var(--color-border);
36
+ border-radius: 0.25em;
37
+ background: var(--color-bg-0);
38
+ color: var(--color-text-secondary);
39
+ cursor: pointer;
40
+ transition:
41
+ color var(--transition-fast),
42
+ background-color var(--transition-fast);
43
+ }
44
+
45
+ .light-dark-toggle:hover {
46
+ color: var(--color-text);
47
+ background: var(--color-bg-1);
48
+ }
49
+ </style>
@@ -0,0 +1,305 @@
1
+ # NumberInput
2
+
3
+ A number input field with optional slider, percent mode, and validation.
4
+
5
+ ## Examples
6
+
7
+ ### Basic
8
+
9
+ <script setup>
10
+ import { ref } from 'vue'
11
+ const days = ref(10)
12
+ const population = ref(100000)
13
+ const coverage = ref(0.5)
14
+ const r0 = ref(3.5)
15
+ </script>
16
+
17
+ <ComponentDemo>
18
+ <div style="width: 300px">
19
+ <NumberInput v-model="days" label="Days" placeholder="Number of days" />
20
+ </div>
21
+
22
+ <template #code>
23
+
24
+ ```vue
25
+ <script setup>
26
+ import { ref } from "vue";
27
+ const days = ref(10);
28
+ </script>
29
+
30
+ <NumberInput v-model="days" label="Days" placeholder="Number of days" />
31
+ ```
32
+
33
+ </template>
34
+ </ComponentDemo>
35
+
36
+ ### With hint and validation
37
+
38
+ <ComponentDemo>
39
+ <div style="width: 300px">
40
+ <NumberInput
41
+ v-model="population"
42
+ label="Population"
43
+ hint="Total number of individuals"
44
+ :min="1000"
45
+ :max="100000"
46
+ :step="1"
47
+ />
48
+ </div>
49
+
50
+ <template #code>
51
+
52
+ ```vue
53
+ <NumberInput
54
+ v-model="population"
55
+ label="Population"
56
+ hint="Total number of individuals"
57
+ :min="1000"
58
+ :max="100000"
59
+ :step="1"
60
+ />
61
+ ```
62
+
63
+ </template>
64
+ </ComponentDemo>
65
+
66
+ ### Percent mode
67
+
68
+ <ComponentDemo>
69
+ <div style="width: 300px">
70
+ <NumberInput
71
+ v-model="coverage"
72
+ label="Vaccination coverage"
73
+ percent
74
+ :max="1"
75
+ />
76
+ </div>
77
+
78
+ <template #code>
79
+
80
+ ```vue
81
+ <NumberInput v-model="coverage" label="Vaccination coverage" percent :max="1" />
82
+ ```
83
+
84
+ </template>
85
+ </ComponentDemo>
86
+
87
+ ### Slider
88
+
89
+ <ComponentDemo>
90
+ <div style="width: 300px">
91
+ <NumberInput
92
+ v-model="r0"
93
+ label="R0"
94
+ hint="Basic reproduction number"
95
+ :step="0.1"
96
+ :min="1"
97
+ :max="18"
98
+ slider
99
+ />
100
+ </div>
101
+
102
+ <template #code>
103
+
104
+ ```vue
105
+ <NumberInput
106
+ v-model="r0"
107
+ label="R0"
108
+ hint="Basic reproduction number"
109
+ :step="0.1"
110
+ :min="1"
111
+ :max="18"
112
+ slider
113
+ />
114
+ ```
115
+
116
+ </template>
117
+ </ComponentDemo>
118
+
119
+ ### Live slider
120
+
121
+ With `live`, the model updates while dragging the slider thumb rather than only on release.
122
+
123
+ <ComponentDemo>
124
+ <div style="width: 300px">
125
+ <NumberInput
126
+ v-model="coverage"
127
+ label="Vaccination coverage"
128
+ percent
129
+ slider
130
+ live
131
+ :max="1"
132
+ />
133
+ </div>
134
+
135
+ <template #code>
136
+
137
+ ```vue
138
+ <NumberInput
139
+ v-model="coverage"
140
+ label="Vaccination coverage"
141
+ percent
142
+ slider
143
+ live
144
+ :max="1"
145
+ />
146
+ ```
147
+
148
+ </template>
149
+ </ComponentDemo>
150
+
151
+ ### Live input
152
+
153
+ With `live` on a regular input, the model updates as you type (debounced 300ms). Arrow keys and spinner buttons commit immediately.
154
+
155
+ <ComponentDemo>
156
+ <div style="width: 300px">
157
+ <NumberInput v-model="days" label="Days" live />
158
+ </div>
159
+
160
+ <template #code>
161
+
162
+ ```vue
163
+ <NumberInput v-model="days" label="Days" live />
164
+ ```
165
+
166
+ </template>
167
+ </ComponentDemo>
168
+
169
+ ### Integer type
170
+
171
+ With `number-type="integer"`, decimal values are truncated to whole numbers on commit. When combined with `percent`, the display value (e.g. 42%) is treated as the integer — so internal values like 0.42 are valid.
172
+
173
+ <ComponentDemo>
174
+ <div style="width: 300px">
175
+ <NumberInput v-model="days" label="Steps" number-type="integer" />
176
+ </div>
177
+
178
+ <template #code>
179
+
180
+ ```vue
181
+ <NumberInput v-model="days" label="Steps" number-type="integer" />
182
+ ```
183
+
184
+ </template>
185
+ </ComponentDemo>
186
+
187
+ ### Decimal places
188
+
189
+ Display precision is inferred from `step` (e.g. `step="0.001"` in percent mode
190
+ shows tenths of a percent). Set `decimals` explicitly to override.
191
+
192
+ <ComponentDemo>
193
+ <div style="width: 300px; display: flex; flex-direction: column; gap: 0.75em">
194
+ <NumberInput
195
+ v-model="coverage"
196
+ label="Coverage (inferred from step)"
197
+ percent
198
+ :step="0.001"
199
+ :max="1"
200
+ />
201
+ <NumberInput
202
+ v-model="r0"
203
+ label="R0 (explicit decimals)"
204
+ :decimals="3"
205
+ :min="0"
206
+ :max="18"
207
+ />
208
+ </div>
209
+
210
+ <template #code>
211
+
212
+ ```vue
213
+ <NumberInput
214
+ v-model="coverage"
215
+ label="Coverage"
216
+ percent
217
+ :step="0.001"
218
+ :max="1"
219
+ />
220
+ <NumberInput v-model="r0" label="R0" :decimals="3" :min="0" :max="18" />
221
+ ```
222
+
223
+ </template>
224
+ </ComponentDemo>
225
+
226
+ ### Required
227
+
228
+ With `required`, clearing the field shows a validation error on commit.
229
+
230
+ <ComponentDemo>
231
+ <div style="width: 300px">
232
+ <NumberInput v-model="days" label="Days" required />
233
+ </div>
234
+
235
+ <template #code>
236
+
237
+ ```vue
238
+ <NumberInput v-model="days" label="Days" required />
239
+ ```
240
+
241
+ </template>
242
+ </ComponentDemo>
243
+
244
+ Combine `required` with `live` to validate as the user types (debounced).
245
+
246
+ <ComponentDemo>
247
+ <div style="width: 300px; display: flex; flex-direction: column; gap: 0.75em">
248
+ <NumberInput v-model="days" label="Days (on blur)" required />
249
+ <NumberInput v-model="days" label="Days (live)" required live />
250
+ </div>
251
+
252
+ <template #code>
253
+
254
+ ```vue
255
+ <NumberInput v-model="days" label="Days (on blur)" required />
256
+ <NumberInput v-model="days" label="Days (live)" required live />
257
+ ```
258
+
259
+ </template>
260
+ </ComponentDemo>
261
+
262
+ ### Hidden label
263
+
264
+ Use `hide-label` to visually hide the label while keeping it available to
265
+ screen readers. Useful when a heading or surrounding context already describes
266
+ the input visually.
267
+
268
+ <ComponentDemo>
269
+ <div style="width: 300px">
270
+ <NumberInput v-model="days" label="Days" hide-label />
271
+ </div>
272
+
273
+ <template #code>
274
+
275
+ ```vue
276
+ <NumberInput v-model="days" label="Days" hide-label />
277
+ ```
278
+
279
+ </template>
280
+ </ComponentDemo>
281
+
282
+ ## Model
283
+
284
+ | Name | Type |
285
+ |------|------|
286
+ | `v-model` | `number` |
287
+
288
+ ## Props
289
+
290
+ | Prop | Type | Required | Default |
291
+ |------|------|----------|---------|
292
+ | `label` | `string` | No | — |
293
+ | `hideLabel` | `boolean` | No | — |
294
+ | `placeholder` | `string` | No | — |
295
+ | `step` | `number` | No | — |
296
+ | `min` | `number` | No | — |
297
+ | `max` | `number` | No | — |
298
+ | `hint` | `string` | No | — |
299
+ | `percent` | `boolean` | No | — |
300
+ | `slider` | `boolean` | No | — |
301
+ | `live` | `boolean` | No | — |
302
+ | `numberType` | `"integer" \| "float"` | No | — |
303
+ | `required` | `boolean` | No | — |
304
+ | `decimals` | `number` | No | — |
305
+