@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.
Files changed (78) hide show
  1. package/dist/style.css +1 -1
  2. package/dist/trees.es.js +4084 -4180
  3. package/dist/trees.umd.js +10 -10
  4. package/package.json +5 -5
  5. package/src/lib-components/forms/BaseInput.vue +21 -32
  6. package/src/lib-components/forms/Checkbox.vue +8 -9
  7. package/src/lib-components/forms/DateRangePicker.vue +21 -22
  8. package/src/lib-components/forms/DateTimeInput.vue +14 -24
  9. package/src/lib-components/forms/MultiCheckboxes.vue +33 -35
  10. package/src/lib-components/forms/Radio.vue +8 -11
  11. package/src/lib-components/forms/RadioCards.vue +8 -12
  12. package/src/lib-components/forms/Select.vue +10 -26
  13. package/src/lib-components/forms/TextArea.vue +11 -17
  14. package/src/lib-components/forms/Toggle.vue +6 -7
  15. package/src/lib-components/forms/YesOrNoRadio.vue +10 -12
  16. package/src/lib-components/layout/DateFilter.vue +8 -4
  17. package/src/lib-components/lists/DynamicTable.vue +7 -8
  18. package/src/lib-components/navigation/ActionsDropdown.vue +2 -0
  19. package/src/lib-components/navigation/Paginator.vue +17 -20
  20. package/src/lib-components/navigation/Tabs.vue +6 -18
  21. package/src/lib-components/overlays/ContentModal.vue +13 -9
  22. package/src/lib-components/overlays/Modal.vue +14 -11
  23. package/src/lib-components/overlays/Popover/Popover.vue +2 -0
  24. package/src/lib-components/overlays/Slideover.vue +13 -15
  25. package/types/composables/forms.d.ts +16 -2
  26. package/types/composables/nav.d.ts +1 -1
  27. package/types/composables/useActionItems.d.ts +1 -1
  28. package/types/composables/useFlashes.d.ts +1 -1
  29. package/types/composables/useSpinner.d.ts +6 -6
  30. package/types/composables/useTable.d.ts +1 -1
  31. package/types/entry.d.ts +0 -2
  32. package/types/helpers/Slots.d.ts +2 -0
  33. package/types/lib-components/forms/BaseInput.vue.d.ts +13 -36
  34. package/types/lib-components/forms/Checkbox.vue.d.ts +10 -35
  35. package/types/lib-components/forms/DateRangePicker.vue.d.ts +15 -38
  36. package/types/lib-components/forms/DateTimeInput.vue.d.ts +10 -35
  37. package/types/lib-components/forms/FieldsetLegend.vue.d.ts +4 -29
  38. package/types/lib-components/forms/InputError.vue.d.ts +4 -25
  39. package/types/lib-components/forms/InputHelp.vue.d.ts +4 -27
  40. package/types/lib-components/forms/InputLabel.vue.d.ts +4 -29
  41. package/types/lib-components/forms/MultiCheckboxes.vue.d.ts +13 -36
  42. package/types/lib-components/forms/Radio.vue.d.ts +10 -35
  43. package/types/lib-components/forms/RadioCards.vue.d.ts +16 -13
  44. package/types/lib-components/forms/Select.vue.d.ts +10 -35
  45. package/types/lib-components/forms/TextArea.vue.d.ts +10 -35
  46. package/types/lib-components/forms/Toggle.vue.d.ts +12 -36
  47. package/types/lib-components/forms/YesOrNoRadio.vue.d.ts +10 -35
  48. package/types/lib-components/indicators/InlineAlert.vue.d.ts +11 -42
  49. package/types/lib-components/indicators/ProgressCircles.vue.d.ts +3 -12
  50. package/types/lib-components/indicators/ProgressCirclesLabeled.vue.d.ts +3 -12
  51. package/types/lib-components/indicators/XYSpinner.vue.d.ts +1 -1
  52. package/types/lib-components/layout/DateFilter.vue.d.ts +7 -16
  53. package/types/lib-components/layout/SidebarLayout.vue.d.ts +4 -25
  54. package/types/lib-components/layout/StackedLayout.vue.d.ts +4 -25
  55. package/types/lib-components/lists/Cards.vue.d.ts +3 -12
  56. package/types/lib-components/lists/DataTable.vue.d.ts +4 -31
  57. package/types/lib-components/lists/DetailList.vue.d.ts +5 -36
  58. package/types/lib-components/lists/DownloadCell.vue.d.ts +3 -12
  59. package/types/lib-components/lists/DynamicTable.vue.d.ts +8 -35
  60. package/types/lib-components/lists/StaticTable.vue.d.ts +21 -0
  61. package/types/lib-components/lists/StaticTableActionSlot.vue.d.ts +27 -0
  62. package/types/lib-components/lists/Table.vue.d.ts +39 -0
  63. package/types/lib-components/lists/TableActionButtons.vue.d.ts +4 -25
  64. package/types/lib-components/navigation/ActionsDropdown.vue.d.ts +4 -26
  65. package/types/lib-components/navigation/ActionsDropdownCallback.vue.d.ts +18 -0
  66. package/types/lib-components/navigation/ActionsDropdownEmit.vue.d.ts +22 -0
  67. package/types/lib-components/navigation/Paginator.vue.d.ts +7 -17
  68. package/types/lib-components/navigation/Steps.vue.d.ts +6 -33
  69. package/types/lib-components/navigation/Tabs.vue.d.ts +12 -37
  70. package/types/lib-components/overlays/AlertModal.vue.d.ts +68 -0
  71. package/types/lib-components/overlays/ContentModal.vue.d.ts +14 -35
  72. package/types/lib-components/overlays/Flash.vue.d.ts +1 -1
  73. package/types/lib-components/overlays/Modal.vue.d.ts +19 -49
  74. package/types/lib-components/overlays/Popover/Popover.vue.d.ts +4 -27
  75. package/types/lib-components/overlays/Popover/PopoverContent.vue.d.ts +1 -1
  76. package/types/lib-components/overlays/Slideover.vue.d.ts +12 -21
  77. package/types/lib-components/overlays/Spinner.vue.d.ts +1 -1
  78. 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 { useInputField, defaultInputProps } from "@/composables/forms"
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 onInput = (e: Event) => {
25
- modelState.value = (e.target as HTMLInputElement).value.trim()
26
- inputValidation(e)
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="onInput"
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 emits = defineEmits(["update:modelValue"])
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
- modelValue ? 'bg-xy-blue' : 'bg-gray-200',
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
- modelValue ? 'translate-x-5' : 'translate-x-0',
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 { useInputField, defaultInputProps } from "@/composables/forms"
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="onChange($event, true)"
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="onChange($event, false)"
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: SortDir) => {
25
- emits("sort-dir-changed", sortDir)
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
- emits("date-range-changed", dateRange)
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
- minDate: number
121
- maxDate: number
122
- }): void => {
123
- pagination.value.page = 1
124
- dateRange.value = newDateRange
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 props = defineProps<{
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
- emit("update:modelValue", {
15
- ...props.modelValue,
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 (props.modelValue.totalPages <= 4) {
25
- for (let i = 0; i < props.modelValue.totalPages; 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 = props.modelValue.totalPages - props.modelValue.page
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(props.modelValue.page + i)
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(props.modelValue.totalPages - i)
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
- modelValue.page == 1
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(modelValue.page - 1)"
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
- modelValue.page === i
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
- modelValue.page >= modelValue.totalPages
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(modelValue.page + 1)"
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 emit = defineEmits<{
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 (props.modelValue === currentTab) {
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 (props.modelValue === currentTab) {
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="updateModelValue(tab.value)"
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: "update:modelValue", val: boolean): void
25
+ (e: "close"): void
24
26
  }>()
25
27
 
26
- const updateModelValue = (value: boolean) => {
27
- emit("update:modelValue", value)
28
- }
28
+ watch(open, (isOpen) => {
29
+ if (!isOpen) {
30
+ emit("close")
31
+ }
32
+ })
29
33
  </script>
30
34
  <template>
31
- <TransitionRoot as="template" :show="modelValue">
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="modelValue"
37
- @close="updateModelValue(false)"
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="updateModelValue(false)"
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
- const updateModelValue = (value: boolean) => {
39
- emit("update:modelValue", value)
40
- }
40
+ watch(open, (isOpen) => {
41
+ if (!isOpen) {
42
+ emit("close")
43
+ }
44
+ })
41
45
  </script>
42
46
  <template>
43
- <TransitionRoot as="template" :show="modelValue">
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="modelValue"
49
- @close="updateModelValue(false)"
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="updateModelValue(false)"
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="updateModelValue(false)"
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 { ref } from "vue"
10
+ import { watch } from "vue"
11
11
 
12
- const props = defineProps<{
12
+ defineProps<{
13
13
  header: string
14
14
  description: string
15
- modelValue: boolean
16
15
  }>()
17
16
 
18
- const open = ref(props.modelValue)
17
+ const open = defineModel<boolean>({ required: true })
19
18
 
20
19
  const emit = defineEmits<{
21
- (e: "close", val: boolean): void
22
- (e: "update:modelValue", val: boolean): void
20
+ (e: "close"): void
23
21
  }>()
24
22
 
25
- const close = () => {
26
- open.value = false
27
- emit("close", open.value)
28
- emit("update:modelValue", open.value)
29
- }
23
+ watch(open, (isOpen) => {
24
+ if (!isOpen) {
25
+ emit("close")
26
+ }
27
+ })
30
28
  </script>
31
29
  <template>
32
- <TransitionRoot as="template" :show="modelValue">
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="modelValue"
38
- @close="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="close()"
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
- modelState: import("vue").Ref<T["modelValue"]>;
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
  /**