@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,195 @@
1
+ <script setup lang="ts">
2
+ import {
3
+ SelectContent,
4
+ SelectItem,
5
+ SelectItemIndicator,
6
+ SelectItemText,
7
+ SelectPortal,
8
+ SelectRoot,
9
+ SelectTrigger,
10
+ SelectValue,
11
+ SelectViewport,
12
+ useId,
13
+ } from "reka-ui";
14
+
15
+ export interface SelectOption {
16
+ value: string;
17
+ label: string;
18
+ }
19
+
20
+ const model = defineModel<string>();
21
+
22
+ const props = defineProps<{
23
+ label?: string;
24
+ hideLabel?: boolean;
25
+ ariaLabel?: string;
26
+ options: SelectOption[];
27
+ placeholder?: string;
28
+ }>();
29
+
30
+ const id = useId();
31
+ </script>
32
+
33
+ <template>
34
+ <div class="select-box">
35
+ <label
36
+ v-if="label"
37
+ :id="`${id}-label`"
38
+ class="select-label"
39
+ :class="{ 'visually-hidden': hideLabel }"
40
+ >{{ label }}</label
41
+ >
42
+ <SelectRoot v-model="model">
43
+ <SelectTrigger
44
+ class="select-trigger"
45
+ :aria-labelledby="props.label ? `${id}-label` : undefined"
46
+ :aria-label="!props.label ? props.ariaLabel : undefined"
47
+ >
48
+ <SelectValue :placeholder="placeholder" />
49
+ <span class="select-icon" aria-hidden="true">
50
+ <svg
51
+ width="12"
52
+ height="12"
53
+ viewBox="0 0 12 12"
54
+ fill="none"
55
+ stroke="currentColor"
56
+ stroke-width="2"
57
+ stroke-linecap="round"
58
+ stroke-linejoin="round"
59
+ >
60
+ <path d="M3 4.5L6 7.5L9 4.5" />
61
+ </svg>
62
+ </span>
63
+ </SelectTrigger>
64
+ <SelectPortal>
65
+ <SelectContent
66
+ class="select-content"
67
+ position="popper"
68
+ :side-offset="4"
69
+ :body-lock="false"
70
+ >
71
+ <SelectViewport class="select-viewport">
72
+ <SelectItem
73
+ v-for="opt in options"
74
+ :key="opt.value"
75
+ :value="opt.value"
76
+ class="select-item"
77
+ >
78
+ <SelectItemText>{{ opt.label }}</SelectItemText>
79
+ <SelectItemIndicator class="select-indicator">
80
+ <svg
81
+ width="12"
82
+ height="12"
83
+ viewBox="0 0 12 12"
84
+ fill="none"
85
+ stroke="currentColor"
86
+ stroke-width="2"
87
+ stroke-linecap="round"
88
+ stroke-linejoin="round"
89
+ >
90
+ <path d="M2 6L5 9L10 3" />
91
+ </svg>
92
+ </SelectItemIndicator>
93
+ </SelectItem>
94
+ </SelectViewport>
95
+ </SelectContent>
96
+ </SelectPortal>
97
+ </SelectRoot>
98
+ </div>
99
+ </template>
100
+
101
+ <style scoped>
102
+ .select-box {
103
+ display: flex;
104
+ flex-direction: column;
105
+ gap: 0.25em;
106
+ }
107
+
108
+ .select-label {
109
+ font-size: var(--font-size-sm);
110
+ }
111
+
112
+ .select-trigger {
113
+ display: inline-flex;
114
+ align-items: center;
115
+ justify-content: space-between;
116
+ gap: 0.5em;
117
+ font-size: var(--font-size-sm);
118
+ height: 2.5em;
119
+ padding: 0 0.75em;
120
+ border: 1px solid var(--color-border);
121
+ border-radius: 0.375em;
122
+ background: var(--color-bg-0);
123
+ cursor: pointer;
124
+ width: auto;
125
+ font-family: inherit;
126
+ color: inherit;
127
+ line-height: 1.4;
128
+ }
129
+
130
+ .select-trigger:hover {
131
+ border-color: var(--color-border-hover);
132
+ }
133
+
134
+ .select-trigger:focus-visible {
135
+ outline: 2px solid var(--color-primary);
136
+ outline-offset: -1px;
137
+ }
138
+
139
+ .select-trigger[data-placeholder] {
140
+ color: var(--color-text-secondary);
141
+ }
142
+
143
+ .select-icon {
144
+ display: flex;
145
+ align-items: center;
146
+ flex-shrink: 0;
147
+ }
148
+ </style>
149
+
150
+ <style>
151
+ .select-content {
152
+ z-index: 100;
153
+ background: var(--color-bg-0);
154
+ border: 1px solid var(--color-border);
155
+ border-radius: 0.25em;
156
+ box-shadow:
157
+ 0 4px 6px -1px rgba(0, 0, 0, 0.1),
158
+ 0 2px 4px -2px rgba(0, 0, 0, 0.1);
159
+ min-width: var(--reka-select-trigger-width);
160
+ max-height: var(--reka-select-content-available-height);
161
+ }
162
+
163
+ .select-viewport {
164
+ padding: 0.25em;
165
+ }
166
+
167
+ .select-item {
168
+ display: flex;
169
+ align-items: center;
170
+ justify-content: space-between;
171
+ gap: 0.5em;
172
+ padding: 0.25em 0.5em;
173
+ border-radius: 0.25em;
174
+ font-size: var(--font-size-sm);
175
+ white-space: nowrap;
176
+ cursor: pointer;
177
+ user-select: none;
178
+ outline: none;
179
+ }
180
+
181
+ .select-item[data-highlighted] {
182
+ background: var(--color-primary);
183
+ color: white;
184
+ }
185
+
186
+ .select-item[data-state="checked"] {
187
+ font-weight: 600;
188
+ }
189
+
190
+ .select-indicator {
191
+ display: flex;
192
+ align-items: center;
193
+ flex-shrink: 0;
194
+ }
195
+ </style>
@@ -0,0 +1,104 @@
1
+ # SidebarLayout
2
+
3
+ A responsive two-panel layout with a collapsible sidebar and main content area. On mobile, the sidebar becomes an overlay.
4
+
5
+ ## Demo
6
+
7
+ <a href="/cfa-simulator/docs/demos/sidebar-layout/index.html" target="_blank">Open in full window ↗</a>
8
+
9
+ <div style="border: 1px solid var(--vp-c-border); border-radius: 8px; overflow: hidden; height: 500px;">
10
+ <iframe src="/cfa-simulator/docs/demos/sidebar-layout/index.html" style="width: 100%; height: 100%; border: none;" />
11
+ </div>
12
+
13
+ ## Tabs Demo (Router Mode)
14
+
15
+ <a href="/cfa-simulator/docs/demos/sidebar-tabs/index.html" target="_blank">Open in full window ↗</a>
16
+
17
+ <div style="border: 1px solid var(--vp-c-border); border-radius: 8px; overflow: hidden; height: 500px;">
18
+ <iframe src="/cfa-simulator/docs/demos/sidebar-tabs/index.html" style="width: 100%; height: 100%; border: none;" />
19
+ </div>
20
+
21
+ ## Usage
22
+
23
+ ```vue
24
+ <SidebarLayout>
25
+ <template #sidebar>
26
+ <h2>Controls</h2>
27
+ <NumberInput v-model="value" label="Parameter" slider live />
28
+ </template>
29
+ <h1>Main Content</h1>
30
+ <p>Your charts and data go here.</p>
31
+ </SidebarLayout>
32
+ ```
33
+
34
+ ## Slots
35
+
36
+ | Slot | Description |
37
+ | --------- | ------------------------------------------ |
38
+ | `sidebar` | Content rendered in the left sidebar panel |
39
+ | `default` | Main content area |
40
+
41
+ ## Props
42
+
43
+ | Prop | Type | Default | Description |
44
+ | ------------- | --------- | ----------- | ---------------------------------------------------- |
45
+ | `hideTopbar` | `boolean` | `false` | Hides the topbar that contains the light/dark toggle |
46
+ | `tabs` | `Tab[]` | `undefined` | Array of tab definitions to render in the main area |
47
+ | `v-model:tab` | `string` | `undefined` | The active tab value (two-way binding) |
48
+
49
+ ### Tab type
50
+
51
+ ```ts
52
+ interface Tab {
53
+ value: string; // unique identifier
54
+ label: string; // display text
55
+ to?: string; // optional route path for vue-router integration
56
+ }
57
+ ```
58
+
59
+ ## Tabs
60
+
61
+ When the `tabs` prop is provided, a tab bar renders at the top of the main content area. Tabs support two modes:
62
+
63
+ ### Local mode
64
+
65
+ Use `v-model:tab` to control which tab is active. Render content conditionally in the default slot.
66
+
67
+ ```vue
68
+ <script setup>
69
+ import { ref } from "vue";
70
+ const activeTab = ref("chart");
71
+ </script>
72
+
73
+ <SidebarLayout
74
+ v-model:tab="activeTab"
75
+ :tabs="[
76
+ { value: 'chart', label: 'Chart' },
77
+ { value: 'data', label: 'Data' },
78
+ ]"
79
+ >
80
+ <template #sidebar>
81
+ <h2>Controls</h2>
82
+ </template>
83
+ <div v-if="activeTab === 'chart'">Chart content</div>
84
+ <div v-if="activeTab === 'data'">Data table</div>
85
+ </SidebarLayout>
86
+ ```
87
+
88
+ ### Router mode
89
+
90
+ When tabs include a `to` property and vue-router is installed, clicking a tab navigates to that route. The active tab is automatically determined from the current route.
91
+
92
+ ```vue
93
+ <SidebarLayout
94
+ :tabs="[
95
+ { value: 'chart', label: 'Chart', to: '/model/chart' },
96
+ { value: 'data', label: 'Data', to: '/model/data' },
97
+ ]"
98
+ >
99
+ <template #sidebar>
100
+ <h2>Controls</h2>
101
+ </template>
102
+ <RouterView />
103
+ </SidebarLayout>
104
+ ```