@xy-planning-network/trees 0.10.5 → 0.11.0-rc1
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/dist/style.css +1 -1
- package/dist/trees.es.js +4084 -4180
- package/dist/trees.umd.js +10 -10
- package/package.json +5 -5
- package/src/lib-components/forms/BaseInput.vue +21 -32
- package/src/lib-components/forms/Checkbox.vue +8 -9
- package/src/lib-components/forms/DateRangePicker.vue +21 -22
- package/src/lib-components/forms/DateTimeInput.vue +14 -24
- package/src/lib-components/forms/MultiCheckboxes.vue +33 -35
- package/src/lib-components/forms/Radio.vue +8 -11
- package/src/lib-components/forms/RadioCards.vue +8 -12
- package/src/lib-components/forms/Select.vue +10 -26
- package/src/lib-components/forms/TextArea.vue +11 -17
- package/src/lib-components/forms/Toggle.vue +6 -7
- package/src/lib-components/forms/YesOrNoRadio.vue +10 -12
- package/src/lib-components/layout/DateFilter.vue +8 -4
- package/src/lib-components/lists/DynamicTable.vue +7 -8
- package/src/lib-components/navigation/ActionsDropdown.vue +2 -0
- package/src/lib-components/navigation/Paginator.vue +17 -20
- package/src/lib-components/navigation/Tabs.vue +6 -18
- package/src/lib-components/overlays/ContentModal.vue +13 -9
- package/src/lib-components/overlays/Modal.vue +14 -11
- package/src/lib-components/overlays/Popover/Popover.vue +2 -0
- package/src/lib-components/overlays/Slideover.vue +13 -15
- package/types/composables/forms.d.ts +16 -2
- package/types/composables/nav.d.ts +1 -1
- package/types/composables/useActionItems.d.ts +1 -1
- package/types/composables/useFlashes.d.ts +1 -1
- package/types/composables/useSpinner.d.ts +6 -6
- package/types/composables/useTable.d.ts +1 -1
- package/types/entry.d.ts +0 -2
- package/types/helpers/Slots.d.ts +2 -0
- package/types/lib-components/forms/BaseInput.vue.d.ts +13 -36
- package/types/lib-components/forms/Checkbox.vue.d.ts +10 -35
- package/types/lib-components/forms/DateRangePicker.vue.d.ts +15 -38
- package/types/lib-components/forms/DateTimeInput.vue.d.ts +10 -35
- package/types/lib-components/forms/FieldsetLegend.vue.d.ts +4 -29
- package/types/lib-components/forms/InputError.vue.d.ts +4 -25
- package/types/lib-components/forms/InputHelp.vue.d.ts +4 -27
- package/types/lib-components/forms/InputLabel.vue.d.ts +4 -29
- package/types/lib-components/forms/MultiCheckboxes.vue.d.ts +13 -36
- package/types/lib-components/forms/Radio.vue.d.ts +10 -35
- package/types/lib-components/forms/RadioCards.vue.d.ts +16 -13
- package/types/lib-components/forms/Select.vue.d.ts +10 -35
- package/types/lib-components/forms/TextArea.vue.d.ts +10 -35
- package/types/lib-components/forms/Toggle.vue.d.ts +12 -36
- package/types/lib-components/forms/YesOrNoRadio.vue.d.ts +10 -35
- package/types/lib-components/indicators/InlineAlert.vue.d.ts +11 -42
- package/types/lib-components/indicators/ProgressCircles.vue.d.ts +3 -12
- package/types/lib-components/indicators/ProgressCirclesLabeled.vue.d.ts +3 -12
- package/types/lib-components/indicators/XYSpinner.vue.d.ts +1 -1
- package/types/lib-components/layout/DateFilter.vue.d.ts +7 -16
- package/types/lib-components/layout/SidebarLayout.vue.d.ts +4 -25
- package/types/lib-components/layout/StackedLayout.vue.d.ts +4 -25
- package/types/lib-components/lists/Cards.vue.d.ts +3 -12
- package/types/lib-components/lists/DataTable.vue.d.ts +4 -31
- package/types/lib-components/lists/DetailList.vue.d.ts +5 -36
- package/types/lib-components/lists/DownloadCell.vue.d.ts +3 -12
- package/types/lib-components/lists/DynamicTable.vue.d.ts +8 -35
- package/types/lib-components/lists/StaticTable.vue.d.ts +21 -0
- package/types/lib-components/lists/StaticTableActionSlot.vue.d.ts +27 -0
- package/types/lib-components/lists/Table.vue.d.ts +39 -0
- package/types/lib-components/lists/TableActionButtons.vue.d.ts +4 -25
- package/types/lib-components/navigation/ActionsDropdown.vue.d.ts +4 -26
- package/types/lib-components/navigation/ActionsDropdownCallback.vue.d.ts +18 -0
- package/types/lib-components/navigation/ActionsDropdownEmit.vue.d.ts +22 -0
- package/types/lib-components/navigation/Paginator.vue.d.ts +7 -17
- package/types/lib-components/navigation/Steps.vue.d.ts +6 -33
- package/types/lib-components/navigation/Tabs.vue.d.ts +12 -37
- package/types/lib-components/overlays/AlertModal.vue.d.ts +68 -0
- package/types/lib-components/overlays/ContentModal.vue.d.ts +14 -35
- package/types/lib-components/overlays/Flash.vue.d.ts +1 -1
- package/types/lib-components/overlays/Modal.vue.d.ts +19 -49
- package/types/lib-components/overlays/Popover/Popover.vue.d.ts +4 -27
- package/types/lib-components/overlays/Popover/PopoverContent.vue.d.ts +1 -1
- package/types/lib-components/overlays/Slideover.vue.d.ts +12 -21
- package/types/lib-components/overlays/Spinner.vue.d.ts +1 -1
- package/types/lib-components/overlays/Tooltip.vue.d.ts +4 -27
|
@@ -2,7 +2,11 @@
|
|
|
2
2
|
import InputLabel from "./InputLabel.vue"
|
|
3
3
|
import InputHelp from "./InputHelp.vue"
|
|
4
4
|
import InputError from "./InputError.vue"
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
useInputField,
|
|
7
|
+
defaultInputProps,
|
|
8
|
+
defaultModelOpts,
|
|
9
|
+
} from "@/composables/forms"
|
|
6
10
|
import type { TextareaInput } from "@/composables/forms"
|
|
7
11
|
|
|
8
12
|
defineOptions({
|
|
@@ -10,21 +14,11 @@ defineOptions({
|
|
|
10
14
|
})
|
|
11
15
|
|
|
12
16
|
const props = withDefaults(defineProps<TextareaInput>(), defaultInputProps)
|
|
13
|
-
defineEmits(["update:modelValue", "update:error"])
|
|
14
|
-
const {
|
|
15
|
-
aria,
|
|
16
|
-
inputID,
|
|
17
|
-
isRequired,
|
|
18
|
-
modelState,
|
|
19
|
-
errorState,
|
|
20
|
-
onInvalid,
|
|
21
|
-
inputValidation,
|
|
22
|
-
} = useInputField(props)
|
|
23
17
|
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
18
|
+
const modelState = defineModel<TextareaInput["modelValue"]>(defaultModelOpts)
|
|
19
|
+
|
|
20
|
+
const { aria, inputID, isRequired, errorState, onInvalid, inputValidation } =
|
|
21
|
+
useInputField(props)
|
|
28
22
|
</script>
|
|
29
23
|
|
|
30
24
|
<template>
|
|
@@ -38,6 +32,7 @@ const onInput = (e: Event) => {
|
|
|
38
32
|
/>
|
|
39
33
|
<textarea
|
|
40
34
|
:id="inputID"
|
|
35
|
+
v-model="modelState"
|
|
41
36
|
:aria-labelledby="aria.labelledby"
|
|
42
37
|
:aria-describedby="aria.describedby"
|
|
43
38
|
:aria-errormessage="aria.errormessage"
|
|
@@ -49,9 +44,8 @@ const onInput = (e: Event) => {
|
|
|
49
44
|
: 'text-gray-900 ring-gray-300 placeholder:text-gray-400 focus:ring-xy-blue-500',
|
|
50
45
|
]"
|
|
51
46
|
:placeholder="placeholder"
|
|
52
|
-
:value="modelState || undefined"
|
|
53
47
|
v-bind="$attrs"
|
|
54
|
-
@input="
|
|
48
|
+
@input="inputValidation"
|
|
55
49
|
@invalid="onInvalid"
|
|
56
50
|
/>
|
|
57
51
|
<InputHelp :id="aria.describedby" class="mt-1" :text="help" />
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
} from "@headlessui/vue"
|
|
8
8
|
import InputLabel from "@/lib-components/forms/InputLabel.vue"
|
|
9
9
|
import InputHelp from "@/lib-components/forms/InputHelp.vue"
|
|
10
|
-
import { hasAttribute } from "@/composables/forms"
|
|
10
|
+
import { defaultModelOpts, hasAttribute } from "@/composables/forms"
|
|
11
11
|
import { computed, useAttrs } from "vue"
|
|
12
12
|
|
|
13
13
|
defineOptions({
|
|
@@ -16,7 +16,6 @@ defineOptions({
|
|
|
16
16
|
|
|
17
17
|
withDefaults(
|
|
18
18
|
defineProps<{
|
|
19
|
-
modelValue?: boolean
|
|
20
19
|
label?: string
|
|
21
20
|
help?: string
|
|
22
21
|
}>(),
|
|
@@ -26,7 +25,8 @@ withDefaults(
|
|
|
26
25
|
}
|
|
27
26
|
)
|
|
28
27
|
|
|
29
|
-
const
|
|
28
|
+
const switchState = defineModel<boolean>(defaultModelOpts)
|
|
29
|
+
|
|
30
30
|
const attrs = useAttrs()
|
|
31
31
|
const isDisabled = computed(() => {
|
|
32
32
|
return hasAttribute(attrs, "disabled")
|
|
@@ -35,20 +35,19 @@ const isDisabled = computed(() => {
|
|
|
35
35
|
<template>
|
|
36
36
|
<SwitchGroup as="div" class="flex items-start">
|
|
37
37
|
<Switch
|
|
38
|
+
v-model="switchState"
|
|
38
39
|
:class="[
|
|
39
|
-
|
|
40
|
+
switchState ? 'bg-xy-blue' : 'bg-gray-200',
|
|
40
41
|
isDisabled ? 'opacity-75 cursor-not-allowed' : 'cursor-pointer',
|
|
41
42
|
'relative inline-flex shrink-0 h-6 w-11 border-2 border-transparent rounded-full transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-xy-blue-500',
|
|
42
43
|
]"
|
|
43
44
|
:disabled="isDisabled"
|
|
44
|
-
:model-value="modelValue"
|
|
45
|
-
@update:model-value="emits('update:modelValue', $event)"
|
|
46
45
|
>
|
|
47
46
|
<span v-if="!label" class="sr-only">Use</span>
|
|
48
47
|
<span
|
|
49
48
|
aria-hidden="true"
|
|
50
49
|
:class="[
|
|
51
|
-
|
|
50
|
+
switchState ? 'translate-x-5' : 'translate-x-0',
|
|
52
51
|
'pointer-events-none inline-block h-5 w-5 rounded-full bg-white shadow transform ring-0 transition ease-in-out duration-200',
|
|
53
52
|
]"
|
|
54
53
|
/>
|
|
@@ -3,7 +3,11 @@ import FieldsetLegend from "./FieldsetLegend.vue"
|
|
|
3
3
|
import InputLabel from "./InputLabel.vue"
|
|
4
4
|
import InputHelp from "./InputHelp.vue"
|
|
5
5
|
import InputError from "./InputError.vue"
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
useInputField,
|
|
8
|
+
defaultInputProps,
|
|
9
|
+
defaultModelOpts,
|
|
10
|
+
} from "@/composables/forms"
|
|
7
11
|
import type { BooleanInput } from "@/composables/forms"
|
|
8
12
|
|
|
9
13
|
defineOptions({
|
|
@@ -11,23 +15,17 @@ defineOptions({
|
|
|
11
15
|
})
|
|
12
16
|
|
|
13
17
|
const props = withDefaults(defineProps<BooleanInput>(), defaultInputProps)
|
|
18
|
+
const modelState = defineModel<BooleanInput["modelValue"]>(defaultModelOpts)
|
|
14
19
|
|
|
15
|
-
defineEmits(["update:modelValue", "update:error"])
|
|
16
20
|
const {
|
|
17
21
|
aria,
|
|
18
22
|
isDisabled,
|
|
19
23
|
isRequired,
|
|
20
24
|
nameAttr,
|
|
21
|
-
modelState,
|
|
22
25
|
errorState,
|
|
23
26
|
onInvalid,
|
|
24
27
|
validate,
|
|
25
28
|
} = useInputField(props)
|
|
26
|
-
|
|
27
|
-
const onChange = (e: Event, val: boolean) => {
|
|
28
|
-
modelState.value = val
|
|
29
|
-
validate(e)
|
|
30
|
-
}
|
|
31
29
|
</script>
|
|
32
30
|
|
|
33
31
|
<template>
|
|
@@ -63,6 +61,7 @@ const onChange = (e: Event, val: boolean) => {
|
|
|
63
61
|
>
|
|
64
62
|
<input
|
|
65
63
|
:id="`${nameAttr}-true`"
|
|
64
|
+
v-model="modelState"
|
|
66
65
|
type="radio"
|
|
67
66
|
:class="[
|
|
68
67
|
'h-4 w-4 text-xy-blue cursor-pointer',
|
|
@@ -74,9 +73,8 @@ const onChange = (e: Event, val: boolean) => {
|
|
|
74
73
|
]"
|
|
75
74
|
:name="nameAttr"
|
|
76
75
|
:value="true"
|
|
77
|
-
:checked="modelState === true"
|
|
78
76
|
v-bind="$attrs"
|
|
79
|
-
@change="
|
|
77
|
+
@change="validate"
|
|
80
78
|
@invalid="onInvalid"
|
|
81
79
|
/>
|
|
82
80
|
<InputLabel class="ml-3" label="Yes" tag="span" />
|
|
@@ -89,6 +87,7 @@ const onChange = (e: Event, val: boolean) => {
|
|
|
89
87
|
>
|
|
90
88
|
<input
|
|
91
89
|
:id="`${nameAttr}-false`"
|
|
90
|
+
v-model="modelState"
|
|
92
91
|
type="radio"
|
|
93
92
|
:class="[
|
|
94
93
|
'h-4 w-4 text-xy-blue cursor-pointer',
|
|
@@ -100,9 +99,8 @@ const onChange = (e: Event, val: boolean) => {
|
|
|
100
99
|
]"
|
|
101
100
|
:name="nameAttr"
|
|
102
101
|
:value="false"
|
|
103
|
-
:checked="modelState === false"
|
|
104
102
|
v-bind="$attrs"
|
|
105
|
-
@change="
|
|
103
|
+
@change="validate"
|
|
106
104
|
@invalid="onInvalid"
|
|
107
105
|
/>
|
|
108
106
|
<InputLabel class="ml-3" label="No" tag="span" />
|
|
@@ -21,12 +21,16 @@ const emits = defineEmits<{
|
|
|
21
21
|
(e: "date-range-changed", val: DateRange): void
|
|
22
22
|
}>()
|
|
23
23
|
|
|
24
|
-
const sortDirChanged = (sortDir:
|
|
25
|
-
|
|
24
|
+
const sortDirChanged = (sortDir: unknown) => {
|
|
25
|
+
if (sortDir === "asc" || sortDir === "desc") {
|
|
26
|
+
emits("sort-dir-changed", sortDir)
|
|
27
|
+
}
|
|
26
28
|
}
|
|
27
29
|
|
|
28
|
-
const dateRangeChanged = (dateRange: DateRange) => {
|
|
29
|
-
|
|
30
|
+
const dateRangeChanged = (dateRange: DateRange | undefined) => {
|
|
31
|
+
if (dateRange) {
|
|
32
|
+
emits("date-range-changed", dateRange)
|
|
33
|
+
}
|
|
30
34
|
}
|
|
31
35
|
</script>
|
|
32
36
|
<template>
|
|
@@ -12,7 +12,7 @@ import type {
|
|
|
12
12
|
} from "@/composables/table"
|
|
13
13
|
import { useAppFlasher } from "@/composables/useFlashes"
|
|
14
14
|
import { TrailsRespPaged } from "@/api/client"
|
|
15
|
-
import { DateRangeProps } from "@/composables/date"
|
|
15
|
+
import { DateRange, DateRangeProps } from "@/composables/date"
|
|
16
16
|
import { useTable } from "@/composables/useTable"
|
|
17
17
|
import TableActionButtons from "./TableActionButtons.vue"
|
|
18
18
|
|
|
@@ -116,13 +116,12 @@ const pagination = ref({
|
|
|
116
116
|
})
|
|
117
117
|
const query = ref("")
|
|
118
118
|
|
|
119
|
-
const dateRangeChanged = (newDateRange: {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
loadAndRender()
|
|
119
|
+
const dateRangeChanged = (newDateRange: DateRange | undefined): void => {
|
|
120
|
+
if (newDateRange) {
|
|
121
|
+
pagination.value.page = 1
|
|
122
|
+
dateRange.value = newDateRange
|
|
123
|
+
loadAndRender()
|
|
124
|
+
}
|
|
126
125
|
}
|
|
127
126
|
const handleSort = (selectedSort: string): void => {
|
|
128
127
|
if (currentSort.value == selectedSort) {
|
|
@@ -17,6 +17,8 @@ const props = withDefaults(
|
|
|
17
17
|
|
|
18
18
|
const { actions, hasActions } = useActionItems(toRef(props, "actions"))
|
|
19
19
|
|
|
20
|
+
// NOTE(spk): there's a circular type refernce between useTemplateRef and useFloating.
|
|
21
|
+
// Hold on moving to useTemplateRef until this is updated in useFloating.
|
|
20
22
|
const trigger = ref<HTMLElement | null>(null)
|
|
21
23
|
const wrapper = ref<HTMLElement | null>(null)
|
|
22
24
|
const { floatingStyles } = useFloating(trigger, wrapper, {
|
|
@@ -2,27 +2,24 @@
|
|
|
2
2
|
import { Pagination } from "@/composables/nav"
|
|
3
3
|
import { computed } from "vue"
|
|
4
4
|
|
|
5
|
-
const
|
|
6
|
-
modelValue: Pagination
|
|
7
|
-
}>()
|
|
8
|
-
|
|
9
|
-
const emit = defineEmits<{
|
|
10
|
-
(e: "update:modelValue", pagination: Pagination): void
|
|
11
|
-
}>()
|
|
5
|
+
const pagination = defineModel<Pagination>({ required: true })
|
|
12
6
|
|
|
13
7
|
const changePage = (page: number): void => {
|
|
14
|
-
|
|
15
|
-
|
|
8
|
+
// NOTE(spk): reminder that defineModel does not change the one-way data flow philosphy of Vue.js
|
|
9
|
+
// replace the entire object to ensure the event is emitted. Directly mutating a single prop will
|
|
10
|
+
// simply be a
|
|
11
|
+
pagination.value = {
|
|
12
|
+
...pagination.value,
|
|
16
13
|
page: page,
|
|
17
|
-
}
|
|
14
|
+
}
|
|
18
15
|
}
|
|
19
16
|
|
|
20
17
|
const pageShortcuts = computed((): number[] => {
|
|
21
18
|
const shortcuts: number[] = []
|
|
22
19
|
|
|
23
20
|
// If total pages is less than or equal to 4, just return 1, 2, 3, 4
|
|
24
|
-
if (
|
|
25
|
-
for (let i = 0; i <
|
|
21
|
+
if (pagination.value.totalPages <= 4) {
|
|
22
|
+
for (let i = 0; i < pagination.value.totalPages; i++) {
|
|
26
23
|
shortcuts.push(i + 1)
|
|
27
24
|
}
|
|
28
25
|
return shortcuts
|
|
@@ -30,10 +27,10 @@ const pageShortcuts = computed((): number[] => {
|
|
|
30
27
|
|
|
31
28
|
// If there are more than 3 pages left, show these
|
|
32
29
|
// e.g. [4, 5, 6, 7] when there are 8 total pages and the current page is 4
|
|
33
|
-
const pagesLeft: number =
|
|
30
|
+
const pagesLeft: number = pagination.value.totalPages - pagination.value.page
|
|
34
31
|
if (pagesLeft >= 3) {
|
|
35
32
|
for (let i = 0; i < 4; i++) {
|
|
36
|
-
shortcuts.push(
|
|
33
|
+
shortcuts.push(pagination.value.page + i)
|
|
37
34
|
}
|
|
38
35
|
return shortcuts
|
|
39
36
|
}
|
|
@@ -41,7 +38,7 @@ const pageShortcuts = computed((): number[] => {
|
|
|
41
38
|
// If there are less than 3 pages left, count backwards from the last page
|
|
42
39
|
// e.g. [5, 6, 7, 8] when on page 5, 6, 7, and 8 and there are 8 total pages
|
|
43
40
|
for (let i = 0; i < 4; i++) {
|
|
44
|
-
shortcuts.unshift(
|
|
41
|
+
shortcuts.unshift(pagination.value.totalPages - i)
|
|
45
42
|
}
|
|
46
43
|
return shortcuts
|
|
47
44
|
})
|
|
@@ -53,11 +50,11 @@ const pageShortcuts = computed((): number[] => {
|
|
|
53
50
|
href="#"
|
|
54
51
|
class="-mt-px border-t-2 border-transparent pt-4 pr-1 inline-flex items-center text-sm leading-5 font-medium focus:outline-none focus:text-gray-700 focus:border-gray-400"
|
|
55
52
|
:class="
|
|
56
|
-
|
|
53
|
+
pagination.page == 1
|
|
57
54
|
? 'text-gray-500 cursor-not-allowed pointer-events-none'
|
|
58
55
|
: 'text-gray-700 hover:text-gray-900 hover:border-gray-300'
|
|
59
56
|
"
|
|
60
|
-
@click.prevent="changePage(
|
|
57
|
+
@click.prevent="changePage(pagination.page - 1)"
|
|
61
58
|
>
|
|
62
59
|
<svg class="mr-3 h-5 w-5" fill="currentColor" viewBox="0 0 20 20">
|
|
63
60
|
<path
|
|
@@ -77,7 +74,7 @@ const pageShortcuts = computed((): number[] => {
|
|
|
77
74
|
href="#"
|
|
78
75
|
class="-mt-px border-t-2 pt-4 px-4 inline-flex items-center text-sm leading-5 font-medium"
|
|
79
76
|
:class="
|
|
80
|
-
|
|
77
|
+
pagination.page === i
|
|
81
78
|
? 'border-blue-500 text-blue-600 focus:outline-none focus:text-blue-800 focus:border-blue-700'
|
|
82
79
|
: 'border-transparent text-gray-700 hover:text-gray-900 hover:border-gray-300 focus:outline-none focus:text-gray-700 focus:border-gray-400'
|
|
83
80
|
"
|
|
@@ -91,11 +88,11 @@ const pageShortcuts = computed((): number[] => {
|
|
|
91
88
|
href="#"
|
|
92
89
|
class="-mt-px border-t-2 border-transparent pt-4 pl-1 inline-flex items-center text-sm leading-5 font-medium focus:outline-none focus:text-gray-700 focus:border-gray-400"
|
|
93
90
|
:class="
|
|
94
|
-
|
|
91
|
+
pagination.page >= pagination.totalPages
|
|
95
92
|
? 'text-gray-500 cursor-not-allowed pointer-events-none'
|
|
96
93
|
: 'text-gray-700 hover:text-gray-900 hover:border-gray-300'
|
|
97
94
|
"
|
|
98
|
-
@click.prevent="changePage(
|
|
95
|
+
@click.prevent="changePage(pagination.page + 1)"
|
|
99
96
|
>
|
|
100
97
|
Next
|
|
101
98
|
<svg class="ml-3 h-5 w-5" fill="currentColor" viewBox="0 0 20 20">
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { computed } from "vue"
|
|
2
|
+
import { computed, defineModel } from "vue"
|
|
3
3
|
|
|
4
4
|
const props = withDefaults(
|
|
5
5
|
defineProps<{
|
|
6
|
-
modelValue: string
|
|
7
6
|
pillDesign?: boolean
|
|
8
7
|
tabs: Array<{
|
|
9
8
|
label: string
|
|
@@ -15,13 +14,7 @@ const props = withDefaults(
|
|
|
15
14
|
}
|
|
16
15
|
)
|
|
17
16
|
|
|
18
|
-
const
|
|
19
|
-
(e: "update:modelValue", val: string): void
|
|
20
|
-
}>()
|
|
21
|
-
|
|
22
|
-
const updateModelValue = (modelValue: string): void => {
|
|
23
|
-
emit("update:modelValue", modelValue)
|
|
24
|
-
}
|
|
17
|
+
const activeTab = defineModel<string>({ required: true })
|
|
25
18
|
|
|
26
19
|
const classes = (currentTab: string, pastFirstTab: boolean): string => {
|
|
27
20
|
let c = ""
|
|
@@ -30,7 +23,7 @@ const classes = (currentTab: string, pastFirstTab: boolean): string => {
|
|
|
30
23
|
c =
|
|
31
24
|
"px-12 py-2 font-semibold text-md leading-5 rounded-t-md focus:outline-none "
|
|
32
25
|
|
|
33
|
-
if (
|
|
26
|
+
if (activeTab.value === currentTab) {
|
|
34
27
|
c = c + "focus:bg-white text-gray-700 bg-white border-b-2 border-blue-500"
|
|
35
28
|
} else {
|
|
36
29
|
c =
|
|
@@ -43,7 +36,7 @@ const classes = (currentTab: string, pastFirstTab: boolean): string => {
|
|
|
43
36
|
|
|
44
37
|
c =
|
|
45
38
|
"px-1 py-4 text-sm font-semibold border-b-2 whitespace-nowrap leading-5 focus:outline-none "
|
|
46
|
-
if (
|
|
39
|
+
if (activeTab.value === currentTab) {
|
|
47
40
|
c =
|
|
48
41
|
c +
|
|
49
42
|
"border-blue-500 text-xy-blue focus:text-blue-800 focus:border-blue-700"
|
|
@@ -66,12 +59,7 @@ const notPillDesign = computed((): boolean => {
|
|
|
66
59
|
<div>
|
|
67
60
|
<div class="sm:hidden" :class="{ 'mb-4': pillDesign }">
|
|
68
61
|
<label for="tabs" class="sr-only">Select a tab</label>
|
|
69
|
-
<Select
|
|
70
|
-
name="tabs"
|
|
71
|
-
:model-value="modelValue"
|
|
72
|
-
:options="tabs"
|
|
73
|
-
@update:model-value="updateModelValue($event)"
|
|
74
|
-
/>
|
|
62
|
+
<Select v-model="activeTab" name="tabs" :options="tabs" />
|
|
75
63
|
</div>
|
|
76
64
|
<div class="hidden sm:block">
|
|
77
65
|
<div :class="{ 'border-b border-gray-200': notPillDesign }">
|
|
@@ -81,7 +69,7 @@ const notPillDesign = computed((): boolean => {
|
|
|
81
69
|
:key="idx"
|
|
82
70
|
href="#"
|
|
83
71
|
:class="classes(tab.value, idx > 0)"
|
|
84
|
-
@click.prevent="
|
|
72
|
+
@click.prevent="activeTab = tab.value"
|
|
85
73
|
v-text="tab.label"
|
|
86
74
|
>
|
|
87
75
|
</a>
|
|
@@ -6,10 +6,10 @@ import {
|
|
|
6
6
|
TransitionChild,
|
|
7
7
|
TransitionRoot,
|
|
8
8
|
} from "@headlessui/vue"
|
|
9
|
+
import { watch } from "vue"
|
|
9
10
|
|
|
10
11
|
withDefaults(
|
|
11
12
|
defineProps<{
|
|
12
|
-
modelValue: boolean
|
|
13
13
|
btnText?: string
|
|
14
14
|
title?: string
|
|
15
15
|
}>(),
|
|
@@ -19,22 +19,26 @@ withDefaults(
|
|
|
19
19
|
}
|
|
20
20
|
)
|
|
21
21
|
|
|
22
|
+
const open = defineModel<boolean>({ required: true })
|
|
23
|
+
|
|
22
24
|
const emit = defineEmits<{
|
|
23
|
-
(e: "
|
|
25
|
+
(e: "close"): void
|
|
24
26
|
}>()
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
watch(open, (isOpen) => {
|
|
29
|
+
if (!isOpen) {
|
|
30
|
+
emit("close")
|
|
31
|
+
}
|
|
32
|
+
})
|
|
29
33
|
</script>
|
|
30
34
|
<template>
|
|
31
|
-
<TransitionRoot as="template" :show="
|
|
35
|
+
<TransitionRoot as="template" :show="open">
|
|
32
36
|
<Dialog
|
|
33
37
|
as="div"
|
|
34
38
|
static
|
|
35
39
|
class="fixed z-30 inset-0 overflow-y-auto"
|
|
36
|
-
:open="
|
|
37
|
-
@close="
|
|
40
|
+
:open="open"
|
|
41
|
+
@close="open = false"
|
|
38
42
|
>
|
|
39
43
|
<div
|
|
40
44
|
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"
|
|
@@ -84,7 +88,7 @@ const updateModelValue = (value: boolean) => {
|
|
|
84
88
|
<button
|
|
85
89
|
type="button"
|
|
86
90
|
class="inline-flex justify-center w-full xy-btn"
|
|
87
|
-
@click="
|
|
91
|
+
@click="open = false"
|
|
88
92
|
>
|
|
89
93
|
{{ btnText }}
|
|
90
94
|
</button>
|
|
@@ -7,12 +7,12 @@ import {
|
|
|
7
7
|
TransitionRoot,
|
|
8
8
|
} from "@headlessui/vue"
|
|
9
9
|
import { XIcon } from "@heroicons/vue/outline"
|
|
10
|
+
import { watch } from "vue"
|
|
10
11
|
|
|
11
12
|
withDefaults(
|
|
12
13
|
defineProps<{
|
|
13
14
|
destructive?: boolean
|
|
14
15
|
disabled?: boolean
|
|
15
|
-
modelValue: boolean
|
|
16
16
|
wide?: boolean
|
|
17
17
|
submitText?: string
|
|
18
18
|
title?: string
|
|
@@ -26,27 +26,31 @@ withDefaults(
|
|
|
26
26
|
}
|
|
27
27
|
)
|
|
28
28
|
|
|
29
|
+
const open = defineModel<boolean>({ required: true })
|
|
30
|
+
|
|
29
31
|
const emit = defineEmits<{
|
|
32
|
+
(e: "close"): void
|
|
30
33
|
(e: "submit"): void
|
|
31
|
-
(e: "update:modelValue", val: boolean): void
|
|
32
34
|
}>()
|
|
33
35
|
|
|
34
36
|
const submit = () => {
|
|
35
37
|
emit("submit")
|
|
36
38
|
}
|
|
37
39
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
watch(open, (isOpen) => {
|
|
41
|
+
if (!isOpen) {
|
|
42
|
+
emit("close")
|
|
43
|
+
}
|
|
44
|
+
})
|
|
41
45
|
</script>
|
|
42
46
|
<template>
|
|
43
|
-
<TransitionRoot as="template" :show="
|
|
47
|
+
<TransitionRoot as="template" :show="open">
|
|
44
48
|
<Dialog
|
|
45
49
|
as="div"
|
|
46
50
|
static
|
|
47
51
|
class="fixed z-30 inset-0 overflow-y-auto"
|
|
48
|
-
:open="
|
|
49
|
-
@close="
|
|
52
|
+
:open="open"
|
|
53
|
+
@close="open = false"
|
|
50
54
|
>
|
|
51
55
|
<div
|
|
52
56
|
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"
|
|
@@ -88,7 +92,7 @@ const updateModelValue = (value: boolean) => {
|
|
|
88
92
|
<button
|
|
89
93
|
type="button"
|
|
90
94
|
class="bg-white rounded-md text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
|
|
91
|
-
@click="
|
|
95
|
+
@click="open = false"
|
|
92
96
|
>
|
|
93
97
|
<span class="sr-only">Close</span>
|
|
94
98
|
<XIcon class="h-6 w-6" aria-hidden="true" />
|
|
@@ -119,10 +123,9 @@ const updateModelValue = (value: boolean) => {
|
|
|
119
123
|
v-text="submitText"
|
|
120
124
|
></button>
|
|
121
125
|
<button
|
|
122
|
-
ref="cancelButtonRef"
|
|
123
126
|
type="button"
|
|
124
127
|
class="xy-btn-neutral mt-3 w-full sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm"
|
|
125
|
-
@click="
|
|
128
|
+
@click="open = false"
|
|
126
129
|
>
|
|
127
130
|
Cancel
|
|
128
131
|
</button>
|
|
@@ -25,6 +25,8 @@ const props = withDefaults(
|
|
|
25
25
|
}
|
|
26
26
|
)
|
|
27
27
|
|
|
28
|
+
// NOTE(spk): there's a circular type reference between useTemplateRef and useFloating.
|
|
29
|
+
// Hold on moving to useTemplateRef until this is updated in useFloating.
|
|
28
30
|
const trigger = ref<HTMLElement | null>(null)
|
|
29
31
|
const wrapper = ref<HTMLElement | null>(null)
|
|
30
32
|
const middleware = computed(() => {
|
|
@@ -7,35 +7,33 @@ import {
|
|
|
7
7
|
TransitionRoot,
|
|
8
8
|
} from "@headlessui/vue"
|
|
9
9
|
import { XIcon } from "@heroicons/vue/outline"
|
|
10
|
-
import {
|
|
10
|
+
import { watch } from "vue"
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
defineProps<{
|
|
13
13
|
header: string
|
|
14
14
|
description: string
|
|
15
|
-
modelValue: boolean
|
|
16
15
|
}>()
|
|
17
16
|
|
|
18
|
-
const open =
|
|
17
|
+
const open = defineModel<boolean>({ required: true })
|
|
19
18
|
|
|
20
19
|
const emit = defineEmits<{
|
|
21
|
-
(e: "close"
|
|
22
|
-
(e: "update:modelValue", val: boolean): void
|
|
20
|
+
(e: "close"): void
|
|
23
21
|
}>()
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
23
|
+
watch(open, (isOpen) => {
|
|
24
|
+
if (!isOpen) {
|
|
25
|
+
emit("close")
|
|
26
|
+
}
|
|
27
|
+
})
|
|
30
28
|
</script>
|
|
31
29
|
<template>
|
|
32
|
-
<TransitionRoot as="template" :show="
|
|
30
|
+
<TransitionRoot as="template" :show="open">
|
|
33
31
|
<Dialog
|
|
34
32
|
as="div"
|
|
35
33
|
static
|
|
36
34
|
class="fixed inset-0 z-20 overflow-hidden bg-black bg-opacity-50"
|
|
37
|
-
:open="
|
|
38
|
-
@close="
|
|
35
|
+
:open="open"
|
|
36
|
+
@close="open = false"
|
|
39
37
|
>
|
|
40
38
|
<div class="absolute inset-0 overflow-hidden">
|
|
41
39
|
<DialogOverlay class="absolute inset-0" />
|
|
@@ -62,7 +60,7 @@ const close = () => {
|
|
|
62
60
|
<div class="ml-3 h-7 flex items-center">
|
|
63
61
|
<button
|
|
64
62
|
class="bg-xy-blue-600 rounded-md text-gray-50 hover:text-white focus:outline-none focus:ring-2 focus:ring-white"
|
|
65
|
-
@click="
|
|
63
|
+
@click="open = false"
|
|
66
64
|
>
|
|
67
65
|
<span class="sr-only">Close panel</span>
|
|
68
66
|
<XIcon class="h-6 w-6" aria-hidden="true" />
|
|
@@ -51,6 +51,21 @@ export declare const defaultInputProps: {
|
|
|
51
51
|
modelValue: undefined;
|
|
52
52
|
placeholder: string;
|
|
53
53
|
};
|
|
54
|
+
/**
|
|
55
|
+
* Form inputs follow an option v-model pattern to allow input field usage
|
|
56
|
+
* where tracking the input binding directly is not necessary.
|
|
57
|
+
*
|
|
58
|
+
* ex: a required checkbox as a confirmation for submitting a form.
|
|
59
|
+
*
|
|
60
|
+
* NOTE(spk): we prevent unexpected default v-model values of a
|
|
61
|
+
* literal 'false' due to an unset v-model prop.
|
|
62
|
+
*
|
|
63
|
+
* see: https://github.com/vuejs/vue/issues/4792#issuecomment-275396426
|
|
64
|
+
*/
|
|
65
|
+
export declare const defaultModelOpts: {
|
|
66
|
+
default: undefined;
|
|
67
|
+
required: boolean;
|
|
68
|
+
};
|
|
54
69
|
export declare const textInputTypes: readonly ["date", "email", "month", "number", "password", "search", "tel", "text", "time", "url", "week"];
|
|
55
70
|
export type TextInputType = (typeof textInputTypes)[number];
|
|
56
71
|
/**
|
|
@@ -72,8 +87,7 @@ export declare const useInputField: <T extends Input>(props: T) => {
|
|
|
72
87
|
isDisabled: import("vue").ComputedRef<boolean>;
|
|
73
88
|
isRequired: import("vue").ComputedRef<boolean>;
|
|
74
89
|
nameAttr: import("vue").ComputedRef<string>;
|
|
75
|
-
|
|
76
|
-
errorState: import("vue").Ref<string>;
|
|
90
|
+
errorState: import("vue").Ref<string, string>;
|
|
77
91
|
onInvalid: (e: Event) => void;
|
|
78
92
|
validate: (e: Event) => void;
|
|
79
93
|
inputValidation: (...args: any[]) => void;
|
|
@@ -158,4 +158,4 @@ export type URLParams<T> = {
|
|
|
158
158
|
* @param initial any Record<string, URLParamValue> like interface
|
|
159
159
|
* @return Ref<T>
|
|
160
160
|
*/
|
|
161
|
-
export declare const useUrlSearchParams: <T>(initial: URLParams<T>) => Ref<import("vue").UnwrapRef<URLParams<T>>>;
|
|
161
|
+
export declare const useUrlSearchParams: <T>(initial: URLParams<T>) => [URLParams<T>] extends [Ref<any, any>] ? import("@vue/shared").IfAny<Ref<any, any> & URLParams<T>, Ref<Ref<any, any> & URLParams<T>, Ref<any, any> & URLParams<T>>, Ref<any, any> & URLParams<T>> : Ref<import("vue").UnwrapRef<URLParams<T>>, URLParams<T> | import("vue").UnwrapRef<URLParams<T>>>;
|
|
@@ -5,7 +5,7 @@ export declare const useActionItems: (items: ActionItem[] | Ref<ActionItem[]>) =
|
|
|
5
5
|
disabled: boolean;
|
|
6
6
|
show: boolean;
|
|
7
7
|
onClick: (...args: any[]) => void;
|
|
8
|
-
icon?: import("vue").RenderFunction | import("vue").FunctionalComponent<{}, {}, any> | undefined;
|
|
8
|
+
icon?: import("vue").RenderFunction | import("vue").FunctionalComponent<{}, {}, any, {}> | undefined;
|
|
9
9
|
label: string;
|
|
10
10
|
}[]>;
|
|
11
11
|
hasActions: import("vue").ComputedRef<boolean>;
|
|
@@ -72,7 +72,7 @@ export declare function useFlashes(flasherConfig?: FlasherConfig): {
|
|
|
72
72
|
success: (message: string, persistent?: boolean) => string;
|
|
73
73
|
genericError: (email?: string, persistent?: boolean) => string;
|
|
74
74
|
};
|
|
75
|
-
flashes: Ref<FlashStore>;
|
|
75
|
+
flashes: Ref<FlashStore, FlashStore>;
|
|
76
76
|
configure: (newConfig: FlasherConfig) => void;
|
|
77
77
|
};
|
|
78
78
|
/**
|