@cfasim-ui/docs 0.5.1 → 0.6.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.
- package/charts/BarChart/BarChart.md +3 -0
- package/charts/BarChart/BarChart.vue +342 -317
- package/charts/ChartMenu/ChartMenu.vue +75 -5
- package/charts/ChoroplethMap/ChoroplethMap.md +5 -0
- package/charts/ChoroplethMap/ChoroplethMap.vue +193 -88
- package/charts/LineChart/LineChart.md +87 -5
- package/charts/LineChart/LineChart.vue +405 -367
- package/charts/_shared/chartProps.ts +10 -0
- package/charts/_shared/useChartFoundation.ts +15 -0
- package/charts/_shared/useChartFullscreen.ts +66 -9
- package/charts/_shared/useChartMenu.ts +13 -6
- package/charts/_shared/useChartTooltip.ts +57 -4
- package/charts/index.ts +0 -2
- package/components/ButtonGroup/ButtonGroup.md +64 -0
- package/components/ButtonGroup/ButtonGroup.vue +91 -0
- package/components/MultiSelect/MultiSelect.md +143 -0
- package/components/MultiSelect/MultiSelect.vue +338 -0
- package/components/ParamEditor/ParamEditor.md +19 -0
- package/components/ParamEditor/ParamEditor.vue +4 -0
- package/components/ParamEditor/ParamEditorImpl.vue +3 -3
- package/components/SelectBox/SelectBox.md +72 -1
- package/components/SelectBox/SelectBox.vue +157 -1
- package/components/ToggleGroup/ToggleGroup.md +163 -0
- package/components/ToggleGroup/ToggleGroup.vue +143 -0
- package/components/index.ts +5 -0
- package/index.json +56 -2
- package/package.json +1 -1
- package/charts/_shared/fullscreen.css +0 -51
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import {
|
|
3
|
+
ComboboxAnchor,
|
|
4
|
+
ComboboxContent,
|
|
5
|
+
ComboboxEmpty,
|
|
6
|
+
ComboboxInput,
|
|
7
|
+
ComboboxItem,
|
|
8
|
+
ComboboxItemIndicator,
|
|
9
|
+
ComboboxPortal,
|
|
10
|
+
ComboboxRoot,
|
|
11
|
+
ComboboxTrigger,
|
|
12
|
+
ComboboxViewport,
|
|
3
13
|
SelectContent,
|
|
4
14
|
SelectItem,
|
|
5
15
|
SelectItemIndicator,
|
|
@@ -25,9 +35,16 @@ const props = defineProps<{
|
|
|
25
35
|
ariaLabel?: string;
|
|
26
36
|
options: SelectOption[];
|
|
27
37
|
placeholder?: string;
|
|
38
|
+
/** Turn the field into a filterable single-select autocomplete (combobox). */
|
|
39
|
+
autocomplete?: boolean;
|
|
28
40
|
}>();
|
|
29
41
|
|
|
30
42
|
const id = useId();
|
|
43
|
+
|
|
44
|
+
// Shows the selected option's label in the combobox input when not filtering.
|
|
45
|
+
function displayValue(value: string) {
|
|
46
|
+
return props.options.find((o) => o.value === value)?.label ?? "";
|
|
47
|
+
}
|
|
31
48
|
</script>
|
|
32
49
|
|
|
33
50
|
<template>
|
|
@@ -35,11 +52,81 @@ const id = useId();
|
|
|
35
52
|
<label
|
|
36
53
|
v-if="label"
|
|
37
54
|
:id="`${id}-label`"
|
|
55
|
+
:for="autocomplete ? `${id}-input` : undefined"
|
|
38
56
|
class="select-label"
|
|
39
57
|
:class="{ 'visually-hidden': hideLabel }"
|
|
40
58
|
>{{ label }}</label
|
|
41
59
|
>
|
|
42
|
-
|
|
60
|
+
|
|
61
|
+
<ComboboxRoot
|
|
62
|
+
v-if="autocomplete"
|
|
63
|
+
v-model="model"
|
|
64
|
+
open-on-click
|
|
65
|
+
class="select-combobox-root"
|
|
66
|
+
>
|
|
67
|
+
<ComboboxAnchor class="select-anchor">
|
|
68
|
+
<ComboboxInput
|
|
69
|
+
:id="`${id}-input`"
|
|
70
|
+
class="select-input"
|
|
71
|
+
:display-value="displayValue"
|
|
72
|
+
:placeholder="placeholder"
|
|
73
|
+
:aria-labelledby="props.label ? `${id}-label` : undefined"
|
|
74
|
+
:aria-label="!props.label ? props.ariaLabel : undefined"
|
|
75
|
+
/>
|
|
76
|
+
<ComboboxTrigger class="select-icon-button" aria-label="Toggle options">
|
|
77
|
+
<span class="select-icon" aria-hidden="true">
|
|
78
|
+
<svg
|
|
79
|
+
width="12"
|
|
80
|
+
height="12"
|
|
81
|
+
viewBox="0 0 12 12"
|
|
82
|
+
fill="none"
|
|
83
|
+
stroke="currentColor"
|
|
84
|
+
stroke-width="2"
|
|
85
|
+
stroke-linecap="round"
|
|
86
|
+
stroke-linejoin="round"
|
|
87
|
+
>
|
|
88
|
+
<path d="M3 4.5L6 7.5L9 4.5" />
|
|
89
|
+
</svg>
|
|
90
|
+
</span>
|
|
91
|
+
</ComboboxTrigger>
|
|
92
|
+
</ComboboxAnchor>
|
|
93
|
+
<ComboboxPortal>
|
|
94
|
+
<ComboboxContent
|
|
95
|
+
class="select-content select-content-autocomplete"
|
|
96
|
+
position="popper"
|
|
97
|
+
:side-offset="4"
|
|
98
|
+
:body-lock="false"
|
|
99
|
+
>
|
|
100
|
+
<ComboboxViewport class="select-viewport">
|
|
101
|
+
<ComboboxEmpty class="select-empty">No matches</ComboboxEmpty>
|
|
102
|
+
<ComboboxItem
|
|
103
|
+
v-for="opt in options"
|
|
104
|
+
:key="opt.value"
|
|
105
|
+
:value="opt.value"
|
|
106
|
+
class="select-item"
|
|
107
|
+
>
|
|
108
|
+
<span>{{ opt.label }}</span>
|
|
109
|
+
<ComboboxItemIndicator class="select-indicator">
|
|
110
|
+
<svg
|
|
111
|
+
width="12"
|
|
112
|
+
height="12"
|
|
113
|
+
viewBox="0 0 12 12"
|
|
114
|
+
fill="none"
|
|
115
|
+
stroke="currentColor"
|
|
116
|
+
stroke-width="2"
|
|
117
|
+
stroke-linecap="round"
|
|
118
|
+
stroke-linejoin="round"
|
|
119
|
+
>
|
|
120
|
+
<path d="M2 6L5 9L10 3" />
|
|
121
|
+
</svg>
|
|
122
|
+
</ComboboxItemIndicator>
|
|
123
|
+
</ComboboxItem>
|
|
124
|
+
</ComboboxViewport>
|
|
125
|
+
</ComboboxContent>
|
|
126
|
+
</ComboboxPortal>
|
|
127
|
+
</ComboboxRoot>
|
|
128
|
+
|
|
129
|
+
<SelectRoot v-else v-model="model">
|
|
43
130
|
<SelectTrigger
|
|
44
131
|
class="select-trigger"
|
|
45
132
|
:aria-labelledby="props.label ? `${id}-label` : undefined"
|
|
@@ -140,6 +227,62 @@ const id = useId();
|
|
|
140
227
|
color: var(--color-text-secondary);
|
|
141
228
|
}
|
|
142
229
|
|
|
230
|
+
/* Autocomplete (combobox) field */
|
|
231
|
+
.select-anchor {
|
|
232
|
+
display: flex;
|
|
233
|
+
align-items: center;
|
|
234
|
+
gap: 0.5em;
|
|
235
|
+
height: 2.5em;
|
|
236
|
+
padding: 0 0.5em 0 0.75em;
|
|
237
|
+
font-size: var(--font-size-sm);
|
|
238
|
+
background: var(--color-bg-0);
|
|
239
|
+
border: 1px solid var(--color-border);
|
|
240
|
+
border-radius: 0.375em;
|
|
241
|
+
transition:
|
|
242
|
+
border-color var(--transition-fast),
|
|
243
|
+
box-shadow var(--transition-fast);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.select-anchor:hover {
|
|
247
|
+
border-color: var(--color-border-hover);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
.select-anchor:focus-within {
|
|
251
|
+
outline: none;
|
|
252
|
+
border-color: var(--color-border-focus);
|
|
253
|
+
box-shadow: var(--shadow-focus);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
.select-input {
|
|
257
|
+
flex: 1;
|
|
258
|
+
min-width: 0;
|
|
259
|
+
height: 100%;
|
|
260
|
+
padding: 0;
|
|
261
|
+
border: none;
|
|
262
|
+
background: none;
|
|
263
|
+
color: inherit;
|
|
264
|
+
font: inherit;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
.select-input:focus {
|
|
268
|
+
outline: none;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
.select-input::placeholder {
|
|
272
|
+
color: var(--color-text-secondary);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
.select-icon-button {
|
|
276
|
+
display: inline-flex;
|
|
277
|
+
align-items: center;
|
|
278
|
+
flex-shrink: 0;
|
|
279
|
+
padding: 0;
|
|
280
|
+
border: none;
|
|
281
|
+
background: none;
|
|
282
|
+
color: inherit;
|
|
283
|
+
cursor: pointer;
|
|
284
|
+
}
|
|
285
|
+
|
|
143
286
|
.select-icon {
|
|
144
287
|
display: flex;
|
|
145
288
|
align-items: center;
|
|
@@ -160,10 +303,23 @@ const id = useId();
|
|
|
160
303
|
max-height: var(--reka-select-content-available-height);
|
|
161
304
|
}
|
|
162
305
|
|
|
306
|
+
/* Combobox exposes the anchor width under its own custom property. */
|
|
307
|
+
.select-content-autocomplete {
|
|
308
|
+
width: var(--reka-combobox-trigger-width);
|
|
309
|
+
max-height: var(--reka-combobox-content-available-height);
|
|
310
|
+
}
|
|
311
|
+
|
|
163
312
|
.select-viewport {
|
|
164
313
|
padding: 0.25em;
|
|
165
314
|
}
|
|
166
315
|
|
|
316
|
+
.select-empty {
|
|
317
|
+
padding: 0.5em;
|
|
318
|
+
font-size: var(--font-size-sm);
|
|
319
|
+
color: var(--color-text-secondary);
|
|
320
|
+
text-align: center;
|
|
321
|
+
}
|
|
322
|
+
|
|
167
323
|
.select-item {
|
|
168
324
|
display: flex;
|
|
169
325
|
align-items: center;
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# ToggleGroup
|
|
2
|
+
|
|
3
|
+
A segmented control that looks like a [`ButtonGroup`](./button-group) but tracks
|
|
4
|
+
which item(s) are pressed. By default it is single-select (like a radio group);
|
|
5
|
+
add `multiple` to let several items be pressed at once. Built on
|
|
6
|
+
[reka-ui's ToggleGroup](https://reka-ui.com/docs/components/toggle-group).
|
|
7
|
+
|
|
8
|
+
## Examples
|
|
9
|
+
|
|
10
|
+
### Single select
|
|
11
|
+
|
|
12
|
+
`v-model` holds the pressed value (a `string`). Clicking the active item again
|
|
13
|
+
clears the selection.
|
|
14
|
+
|
|
15
|
+
<script setup>
|
|
16
|
+
import { ref } from 'vue'
|
|
17
|
+
const interval = ref('weekly')
|
|
18
|
+
const days = ref(['mon', 'wed'])
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<ComponentDemo>
|
|
22
|
+
<ToggleGroup
|
|
23
|
+
v-model="interval"
|
|
24
|
+
label="Interval"
|
|
25
|
+
:options="[
|
|
26
|
+
{ value: 'daily', label: 'Daily' },
|
|
27
|
+
{ value: 'weekly', label: 'Weekly' },
|
|
28
|
+
{ value: 'monthly', label: 'Monthly' },
|
|
29
|
+
]"
|
|
30
|
+
/>
|
|
31
|
+
<p>Selected: {{ interval }}</p>
|
|
32
|
+
|
|
33
|
+
<template #code>
|
|
34
|
+
|
|
35
|
+
```vue
|
|
36
|
+
<script setup>
|
|
37
|
+
import { ref } from "vue";
|
|
38
|
+
const interval = ref("weekly");
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<ToggleGroup
|
|
42
|
+
v-model="interval"
|
|
43
|
+
label="Interval"
|
|
44
|
+
:options="[
|
|
45
|
+
{ value: 'daily', label: 'Daily' },
|
|
46
|
+
{ value: 'weekly', label: 'Weekly' },
|
|
47
|
+
{ value: 'monthly', label: 'Monthly' },
|
|
48
|
+
]"
|
|
49
|
+
/>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
</template>
|
|
53
|
+
</ComponentDemo>
|
|
54
|
+
|
|
55
|
+
### Multiple select
|
|
56
|
+
|
|
57
|
+
With `multiple`, `v-model` is a `string[]` and any number of items can be
|
|
58
|
+
pressed at once.
|
|
59
|
+
|
|
60
|
+
<ComponentDemo>
|
|
61
|
+
<ToggleGroup
|
|
62
|
+
v-model="days"
|
|
63
|
+
multiple
|
|
64
|
+
label="Active days"
|
|
65
|
+
:options="[
|
|
66
|
+
{ value: 'mon', label: 'Mon' },
|
|
67
|
+
{ value: 'tue', label: 'Tue' },
|
|
68
|
+
{ value: 'wed', label: 'Wed' },
|
|
69
|
+
{ value: 'thu', label: 'Thu' },
|
|
70
|
+
{ value: 'fri', label: 'Fri' },
|
|
71
|
+
]"
|
|
72
|
+
/>
|
|
73
|
+
<p>Selected: {{ days.join(', ') || 'none' }}</p>
|
|
74
|
+
|
|
75
|
+
<template #code>
|
|
76
|
+
|
|
77
|
+
```vue
|
|
78
|
+
<script setup>
|
|
79
|
+
import { ref } from "vue";
|
|
80
|
+
const days = ref(["mon", "wed"]);
|
|
81
|
+
</script>
|
|
82
|
+
|
|
83
|
+
<ToggleGroup
|
|
84
|
+
v-model="days"
|
|
85
|
+
multiple
|
|
86
|
+
label="Active days"
|
|
87
|
+
:options="[
|
|
88
|
+
{ value: 'mon', label: 'Mon' },
|
|
89
|
+
{ value: 'tue', label: 'Tue' },
|
|
90
|
+
{ value: 'wed', label: 'Wed' },
|
|
91
|
+
{ value: 'thu', label: 'Thu' },
|
|
92
|
+
{ value: 'fri', label: 'Fri' },
|
|
93
|
+
]"
|
|
94
|
+
/>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
</template>
|
|
98
|
+
</ComponentDemo>
|
|
99
|
+
|
|
100
|
+
### Vertical and disabled options
|
|
101
|
+
|
|
102
|
+
Set `orientation="vertical"` to stack the items, and mark individual options
|
|
103
|
+
`disabled`.
|
|
104
|
+
|
|
105
|
+
<ComponentDemo>
|
|
106
|
+
<ToggleGroup
|
|
107
|
+
model-value="map"
|
|
108
|
+
orientation="vertical"
|
|
109
|
+
aria-label="View"
|
|
110
|
+
:options="[
|
|
111
|
+
{ value: 'map', label: 'Map' },
|
|
112
|
+
{ value: 'chart', label: 'Chart' },
|
|
113
|
+
{ value: 'table', label: 'Table', disabled: true },
|
|
114
|
+
]"
|
|
115
|
+
/>
|
|
116
|
+
|
|
117
|
+
<template #code>
|
|
118
|
+
|
|
119
|
+
```vue
|
|
120
|
+
<ToggleGroup
|
|
121
|
+
v-model="view"
|
|
122
|
+
orientation="vertical"
|
|
123
|
+
aria-label="View"
|
|
124
|
+
:options="[
|
|
125
|
+
{ value: 'map', label: 'Map' },
|
|
126
|
+
{ value: 'chart', label: 'Chart' },
|
|
127
|
+
{ value: 'table', label: 'Table', disabled: true },
|
|
128
|
+
]"
|
|
129
|
+
/>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
</template>
|
|
133
|
+
</ComponentDemo>
|
|
134
|
+
|
|
135
|
+
## Model
|
|
136
|
+
|
|
137
|
+
| Name | Type |
|
|
138
|
+
|------|------|
|
|
139
|
+
| `v-model` | `string \| string[]` |
|
|
140
|
+
|
|
141
|
+
## Props
|
|
142
|
+
|
|
143
|
+
| Prop | Type | Required | Default |
|
|
144
|
+
|------|------|----------|---------|
|
|
145
|
+
| `options` | `ToggleGroupOption[]` | Yes | — |
|
|
146
|
+
| `multiple` | `boolean` | No | — |
|
|
147
|
+
| `label` | `string` | No | — |
|
|
148
|
+
| `hideLabel` | `boolean` | No | — |
|
|
149
|
+
| `ariaLabel` | `string` | No | — |
|
|
150
|
+
| `hint` | `string` | No | — |
|
|
151
|
+
| `disabled` | `boolean` | No | — |
|
|
152
|
+
| `orientation` | `"horizontal" \| "vertical"` | No | `"horizontal"` |
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
### ToggleGroupOption
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
interface ToggleGroupOption {
|
|
159
|
+
value: string;
|
|
160
|
+
label: string;
|
|
161
|
+
disabled?: boolean;
|
|
162
|
+
}
|
|
163
|
+
```
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ToggleGroupItem, ToggleGroupRoot, useId } from "reka-ui";
|
|
3
|
+
import { computed } from "vue";
|
|
4
|
+
import Hint from "../Hint/Hint.vue";
|
|
5
|
+
|
|
6
|
+
export interface ToggleGroupOption {
|
|
7
|
+
value: string;
|
|
8
|
+
label: string;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// `string` in single mode, `string[]` in multiple mode.
|
|
13
|
+
const model = defineModel<string | string[]>();
|
|
14
|
+
|
|
15
|
+
const props = withDefaults(
|
|
16
|
+
defineProps<{
|
|
17
|
+
options: ToggleGroupOption[];
|
|
18
|
+
multiple?: boolean;
|
|
19
|
+
label?: string;
|
|
20
|
+
hideLabel?: boolean;
|
|
21
|
+
ariaLabel?: string;
|
|
22
|
+
hint?: string;
|
|
23
|
+
disabled?: boolean;
|
|
24
|
+
orientation?: "horizontal" | "vertical";
|
|
25
|
+
}>(),
|
|
26
|
+
{ orientation: "horizontal" },
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
const id = useId();
|
|
30
|
+
const type = computed<"single" | "multiple">(() =>
|
|
31
|
+
props.multiple ? "multiple" : "single",
|
|
32
|
+
);
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
<template>
|
|
36
|
+
<div class="toggle-group-field">
|
|
37
|
+
<label
|
|
38
|
+
v-if="label"
|
|
39
|
+
:id="`${id}-label`"
|
|
40
|
+
class="toggle-group-label"
|
|
41
|
+
:class="{ 'visually-hidden': hideLabel }"
|
|
42
|
+
>
|
|
43
|
+
{{ label }}
|
|
44
|
+
<Hint v-if="hint && !hideLabel" :text="hint" />
|
|
45
|
+
</label>
|
|
46
|
+
<ToggleGroupRoot
|
|
47
|
+
v-model="model"
|
|
48
|
+
:type="type"
|
|
49
|
+
:disabled="disabled"
|
|
50
|
+
:orientation="orientation"
|
|
51
|
+
:class="['toggle-group', `toggle-group--${orientation}`]"
|
|
52
|
+
:aria-labelledby="label ? `${id}-label` : undefined"
|
|
53
|
+
:aria-label="!label ? ariaLabel : undefined"
|
|
54
|
+
>
|
|
55
|
+
<ToggleGroupItem
|
|
56
|
+
v-for="opt in options"
|
|
57
|
+
:key="opt.value"
|
|
58
|
+
:value="opt.value"
|
|
59
|
+
:disabled="opt.disabled"
|
|
60
|
+
class="toggle-group-item"
|
|
61
|
+
>
|
|
62
|
+
{{ opt.label }}
|
|
63
|
+
</ToggleGroupItem>
|
|
64
|
+
</ToggleGroupRoot>
|
|
65
|
+
</div>
|
|
66
|
+
</template>
|
|
67
|
+
|
|
68
|
+
<style scoped>
|
|
69
|
+
.toggle-group-field {
|
|
70
|
+
display: flex;
|
|
71
|
+
flex-direction: column;
|
|
72
|
+
gap: 0.25em;
|
|
73
|
+
align-items: flex-start;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.toggle-group-label {
|
|
77
|
+
display: flex;
|
|
78
|
+
align-items: center;
|
|
79
|
+
gap: 0.25em;
|
|
80
|
+
font-size: var(--font-size-sm);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.toggle-group {
|
|
84
|
+
display: inline-flex;
|
|
85
|
+
/* 1px gaps reveal the group background as dividers between items. */
|
|
86
|
+
gap: 1px;
|
|
87
|
+
background: var(--color-border);
|
|
88
|
+
border: 1px solid var(--color-border);
|
|
89
|
+
border-radius: 0.375em;
|
|
90
|
+
/* Clip items to the rounded outer corners. Focus uses an inset outline
|
|
91
|
+
* (below) so it isn't clipped away. */
|
|
92
|
+
overflow: hidden;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.toggle-group--vertical {
|
|
96
|
+
flex-direction: column;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.toggle-group-item {
|
|
100
|
+
appearance: none;
|
|
101
|
+
display: inline-flex;
|
|
102
|
+
align-items: center;
|
|
103
|
+
justify-content: center;
|
|
104
|
+
min-height: 2.5em;
|
|
105
|
+
padding: 0 1em;
|
|
106
|
+
margin: 0;
|
|
107
|
+
border: none;
|
|
108
|
+
background: var(--color-bg-0);
|
|
109
|
+
color: var(--color-text);
|
|
110
|
+
font: inherit;
|
|
111
|
+
font-size: var(--font-size-sm);
|
|
112
|
+
font-weight: 500;
|
|
113
|
+
white-space: nowrap;
|
|
114
|
+
cursor: pointer;
|
|
115
|
+
transition:
|
|
116
|
+
background var(--transition-fast),
|
|
117
|
+
color var(--transition-fast);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.toggle-group-item:hover:not([data-disabled]) {
|
|
121
|
+
background: var(--color-bg-2);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.toggle-group-item[data-state="on"] {
|
|
125
|
+
background: var(--color-primary);
|
|
126
|
+
color: var(--color-text-on-primary);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.toggle-group-item[data-state="on"]:hover:not([data-disabled]) {
|
|
130
|
+
background: var(--color-primary-hover);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.toggle-group-item:focus-visible {
|
|
134
|
+
outline: 2px solid var(--color-primary);
|
|
135
|
+
outline-offset: -2px;
|
|
136
|
+
z-index: 1;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.toggle-group-item[data-disabled] {
|
|
140
|
+
opacity: 0.5;
|
|
141
|
+
cursor: not-allowed;
|
|
142
|
+
}
|
|
143
|
+
</style>
|
package/components/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { default as Box } from "./Box/Box.vue";
|
|
2
2
|
export type { BoxVariant } from "./Box/Box.vue";
|
|
3
3
|
export { default as Button } from "./Button/Button.vue";
|
|
4
|
+
export { default as ButtonGroup } from "./ButtonGroup/ButtonGroup.vue";
|
|
4
5
|
export { default as Container } from "./Container/Container.vue";
|
|
5
6
|
export type { ContainerGap } from "./Container/Container.vue";
|
|
6
7
|
export { default as Expander } from "./Expander/Expander.vue";
|
|
@@ -12,6 +13,8 @@ export type { IconSize } from "./Icon/Icon.vue";
|
|
|
12
13
|
export { registerIcons, hasIcon } from "./Icon/registry";
|
|
13
14
|
export type { IconRegistration, IconVariants } from "./Icon/registry";
|
|
14
15
|
export { default as LightDarkToggle } from "./LightDarkToggle/LightDarkToggle.vue";
|
|
16
|
+
export { default as MultiSelect } from "./MultiSelect/MultiSelect.vue";
|
|
17
|
+
export type { MultiSelectOption } from "./MultiSelect/MultiSelect.vue";
|
|
15
18
|
export { default as NumberInput } from "./NumberInput/NumberInput.vue";
|
|
16
19
|
export type { NumberRange } from "./NumberInput/NumberInput.vue";
|
|
17
20
|
export { default as ParamEditor } from "./ParamEditor/ParamEditor.vue";
|
|
@@ -26,3 +29,5 @@ export type { Tab } from "./SidebarLayout/SidebarLayout.vue";
|
|
|
26
29
|
export { default as Spinner } from "./Spinner/Spinner.vue";
|
|
27
30
|
export { default as TextInput } from "./TextInput/TextInput.vue";
|
|
28
31
|
export { default as Toggle } from "./Toggle/Toggle.vue";
|
|
32
|
+
export { default as ToggleGroup } from "./ToggleGroup/ToggleGroup.vue";
|
|
33
|
+
export type { ToggleGroupOption } from "./ToggleGroup/ToggleGroup.vue";
|
package/index.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.
|
|
2
|
+
"version": "0.6.1",
|
|
3
3
|
"package": "@cfasim-ui/docs",
|
|
4
4
|
"content": {
|
|
5
5
|
"components": [
|
|
@@ -23,6 +23,20 @@
|
|
|
23
23
|
"secondary"
|
|
24
24
|
]
|
|
25
25
|
},
|
|
26
|
+
{
|
|
27
|
+
"name": "ButtonGroup",
|
|
28
|
+
"slug": "button-group",
|
|
29
|
+
"docs": "components/ButtonGroup/ButtonGroup.md",
|
|
30
|
+
"source": "components/ButtonGroup/ButtonGroup.vue",
|
|
31
|
+
"keywords": [
|
|
32
|
+
"button group",
|
|
33
|
+
"buttons",
|
|
34
|
+
"group",
|
|
35
|
+
"toolbar",
|
|
36
|
+
"segmented",
|
|
37
|
+
"joined"
|
|
38
|
+
]
|
|
39
|
+
},
|
|
26
40
|
{
|
|
27
41
|
"name": "Container",
|
|
28
42
|
"slug": "container",
|
|
@@ -76,6 +90,23 @@
|
|
|
76
90
|
"source": "components/Icon/Icon.vue",
|
|
77
91
|
"keywords": []
|
|
78
92
|
},
|
|
93
|
+
{
|
|
94
|
+
"name": "MultiSelect",
|
|
95
|
+
"slug": "multi-select",
|
|
96
|
+
"docs": "components/MultiSelect/MultiSelect.md",
|
|
97
|
+
"source": "components/MultiSelect/MultiSelect.vue",
|
|
98
|
+
"keywords": [
|
|
99
|
+
"multiselect",
|
|
100
|
+
"multi-select",
|
|
101
|
+
"autocomplete",
|
|
102
|
+
"combobox",
|
|
103
|
+
"tags",
|
|
104
|
+
"chips",
|
|
105
|
+
"filter",
|
|
106
|
+
"search",
|
|
107
|
+
"typeahead"
|
|
108
|
+
]
|
|
109
|
+
},
|
|
79
110
|
{
|
|
80
111
|
"name": "NumberInput",
|
|
81
112
|
"slug": "number-input",
|
|
@@ -105,7 +136,15 @@
|
|
|
105
136
|
"slug": "select-box",
|
|
106
137
|
"docs": "components/SelectBox/SelectBox.md",
|
|
107
138
|
"source": "components/SelectBox/SelectBox.vue",
|
|
108
|
-
"keywords": [
|
|
139
|
+
"keywords": [
|
|
140
|
+
"select",
|
|
141
|
+
"dropdown",
|
|
142
|
+
"autocomplete",
|
|
143
|
+
"combobox",
|
|
144
|
+
"filter",
|
|
145
|
+
"search",
|
|
146
|
+
"typeahead"
|
|
147
|
+
]
|
|
109
148
|
},
|
|
110
149
|
{
|
|
111
150
|
"name": "SidebarLayout",
|
|
@@ -134,6 +173,21 @@
|
|
|
134
173
|
"docs": "components/Toggle/Toggle.md",
|
|
135
174
|
"source": "components/Toggle/Toggle.vue",
|
|
136
175
|
"keywords": []
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
"name": "ToggleGroup",
|
|
179
|
+
"slug": "toggle-group",
|
|
180
|
+
"docs": "components/ToggleGroup/ToggleGroup.md",
|
|
181
|
+
"source": "components/ToggleGroup/ToggleGroup.vue",
|
|
182
|
+
"keywords": [
|
|
183
|
+
"toggle group",
|
|
184
|
+
"segmented control",
|
|
185
|
+
"single select",
|
|
186
|
+
"multi select",
|
|
187
|
+
"button group",
|
|
188
|
+
"radio",
|
|
189
|
+
"pressed"
|
|
190
|
+
]
|
|
137
191
|
}
|
|
138
192
|
],
|
|
139
193
|
"charts": [
|
package/package.json
CHANGED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
/* Shared chart styles for the Expand / fullscreen menu item.
|
|
2
|
-
Bundled into @cfasim-ui/charts/style.css via index.ts so it ships
|
|
3
|
-
once for the whole package instead of repeating in every chart SFC. */
|
|
4
|
-
|
|
5
|
-
.line-chart-wrapper:hover .chart-menu-button,
|
|
6
|
-
.bar-chart-wrapper:hover .chart-menu-button,
|
|
7
|
-
.choropleth-wrapper:hover .chart-menu-button,
|
|
8
|
-
.line-chart-wrapper:focus-within .chart-menu-button,
|
|
9
|
-
.bar-chart-wrapper:focus-within .chart-menu-button,
|
|
10
|
-
.choropleth-wrapper:focus-within .chart-menu-button,
|
|
11
|
-
.line-chart-wrapper.is-fullscreen .chart-menu-button,
|
|
12
|
-
.bar-chart-wrapper.is-fullscreen .chart-menu-button,
|
|
13
|
-
.choropleth-wrapper.is-fullscreen .chart-menu-button {
|
|
14
|
-
opacity: 1;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
.line-chart-wrapper.is-fullscreen,
|
|
18
|
-
.bar-chart-wrapper.is-fullscreen,
|
|
19
|
-
.choropleth-wrapper.is-fullscreen {
|
|
20
|
-
position: fixed;
|
|
21
|
-
inset: 0;
|
|
22
|
-
z-index: var(--cfasim-z-fullscreen, 1000);
|
|
23
|
-
background: var(--color-bg-0, #fff);
|
|
24
|
-
color: var(--color-text, inherit);
|
|
25
|
-
padding: 2em;
|
|
26
|
-
box-sizing: border-box;
|
|
27
|
-
display: flex;
|
|
28
|
-
flex-direction: column;
|
|
29
|
-
justify-content: center;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/* ChoroplethMap doesn't go through useChartFoundation, so its SVG keeps
|
|
33
|
-
its prop-driven width/height. Stretch it to fill the expanded box. */
|
|
34
|
-
.choropleth-wrapper.is-fullscreen svg {
|
|
35
|
-
flex: 1 1 auto;
|
|
36
|
-
min-height: 0;
|
|
37
|
-
height: 100%;
|
|
38
|
-
width: 100%;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
.chart-sr-only {
|
|
42
|
-
position: absolute;
|
|
43
|
-
width: 1px;
|
|
44
|
-
height: 1px;
|
|
45
|
-
padding: 0;
|
|
46
|
-
margin: -1px;
|
|
47
|
-
overflow: hidden;
|
|
48
|
-
clip: rect(0, 0, 0, 0);
|
|
49
|
-
white-space: nowrap;
|
|
50
|
-
border: 0;
|
|
51
|
-
}
|