@xy-planning-network/trees 0.7.5-dev → 0.7.5-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 (51) hide show
  1. package/dist/trees.es.js +4007 -3694
  2. package/dist/trees.umd.js +10 -10
  3. package/package.json +2 -2
  4. package/src/lib-components/forms/BaseInput.vue +75 -42
  5. package/src/lib-components/forms/Checkbox.vue +36 -26
  6. package/src/lib-components/forms/DateRangePicker.vue +50 -30
  7. package/src/lib-components/forms/FieldsetLegend.vue +23 -3
  8. package/src/lib-components/forms/InputHelp.vue +1 -1
  9. package/src/lib-components/forms/InputLabel.vue +24 -4
  10. package/src/lib-components/forms/MultiCheckboxes.vue +95 -44
  11. package/src/lib-components/forms/Radio.vue +59 -37
  12. package/src/lib-components/forms/RadioCards.vue +45 -57
  13. package/src/lib-components/forms/Select.vue +37 -40
  14. package/src/lib-components/forms/TextArea.vue +36 -28
  15. package/src/lib-components/forms/Toggle.vue +9 -6
  16. package/src/lib-components/forms/YesOrNoRadio.vue +49 -35
  17. package/src/lib-components/lists/DynamicTable.vue +43 -20
  18. package/types/composables/forms.d.ts +110 -2
  19. package/types/lib-components/forms/BaseInput.vue.d.ts +58 -34
  20. package/types/lib-components/forms/Checkbox.vue.d.ts +50 -29
  21. package/types/lib-components/forms/DateRangePicker.vue.d.ts +71 -39
  22. package/types/lib-components/forms/FieldsetLegend.vue.d.ts +28 -27
  23. package/types/lib-components/forms/InputHelp.vue.d.ts +19 -27
  24. package/types/lib-components/forms/InputLabel.vue.d.ts +28 -27
  25. package/types/lib-components/forms/MultiCheckboxes.vue.d.ts +75 -47
  26. package/types/lib-components/forms/Radio.vue.d.ts +62 -47
  27. package/types/lib-components/forms/RadioCards.vue.d.ts +68 -71
  28. package/types/lib-components/forms/Select.vue.d.ts +55 -39
  29. package/types/lib-components/forms/TextArea.vue.d.ts +50 -32
  30. package/types/lib-components/forms/Toggle.vue.d.ts +27 -32
  31. package/types/lib-components/forms/YesOrNoRadio.vue.d.ts +50 -32
  32. package/types/lib-components/indicators/XYSpinner.vue.d.ts +1 -1
  33. package/types/lib-components/layout/DateFilter.vue.d.ts +28 -20
  34. package/types/lib-components/layout/SidebarLayout.vue.d.ts +38 -32
  35. package/types/lib-components/layout/StackedLayout.vue.d.ts +45 -33
  36. package/types/lib-components/lists/Cards.vue.d.ts +14 -17
  37. package/types/lib-components/lists/DataTable.vue.d.ts +31 -31
  38. package/types/lib-components/lists/DetailList.vue.d.ts +38 -34
  39. package/types/lib-components/lists/DownloadCell.vue.d.ts +18 -15
  40. package/types/lib-components/lists/DynamicTable.vue.d.ts +32 -32
  41. package/types/lib-components/lists/TableActionButtons.vue.d.ts +11 -23
  42. package/types/lib-components/navigation/ActionsDropdown.vue.d.ts +11 -23
  43. package/types/lib-components/navigation/Paginator.vue.d.ts +12 -15
  44. package/types/lib-components/navigation/Steps.vue.d.ts +54 -39
  45. package/types/lib-components/navigation/Tabs.vue.d.ts +34 -34
  46. package/types/lib-components/overlays/ContentModal.vue.d.ts +22 -28
  47. package/types/lib-components/overlays/Modal.vue.d.ts +47 -42
  48. package/types/lib-components/overlays/Popover/Popover.vue.d.ts +23 -31
  49. package/types/lib-components/overlays/Popover/PopoverContent.vue.d.ts +1 -1
  50. package/types/lib-components/overlays/Slideover.vue.d.ts +30 -22
  51. package/types/lib-components/overlays/Tooltip.vue.d.ts +20 -28
@@ -1,51 +1,70 @@
1
1
  <script setup lang="ts">
2
+ import { computed, ref } from "vue"
2
3
  import FieldsetLegend from "./FieldsetLegend.vue"
3
4
  import InputHelp from "./InputHelp.vue"
4
5
  import InputLabel from "./InputLabel.vue"
5
- import { useInputField } from "@/composables/forms"
6
+ import { useInputField, defaultInputProps } from "@/composables/forms"
7
+ import type { OptionsInput, ColumnedInput } from "@/composables/forms"
6
8
 
7
9
  defineOptions({
8
10
  inheritAttrs: false,
9
11
  })
10
12
 
11
- withDefaults(
12
- defineProps<{
13
- options: {
14
- disabled?: boolean
15
- help?: string
16
- label: string
17
- value: string | number
18
- }[]
19
- help?: string
20
- label?: string
21
- modelValue?: string | number
22
- columns?: 2 | 3
23
- }>(),
24
- {
25
- help: "",
26
- label: "",
27
- modelValue: undefined,
28
- columns: undefined,
29
- }
13
+ const props = withDefaults(
14
+ defineProps<OptionsInput & ColumnedInput>(),
15
+ defaultInputProps
30
16
  )
31
- const emits = defineEmits(["update:modelValue"])
32
- const { inputID, isDisabled } = useInputField()
17
+
18
+ defineEmits(["update:modelValue", "update:error"])
19
+
20
+ const radios = ref<HTMLInputElement[]>([])
21
+ // there are multiple radio buttons that could be the target
22
+ // for validation set to the first input
23
+ const targetInput = computed(() => {
24
+ if (radios.value.length === 0) {
25
+ return null
26
+ }
27
+
28
+ return radios.value[0]
29
+ })
30
+ const {
31
+ errorState,
32
+ modelState,
33
+ inputID,
34
+ isDisabled,
35
+ isRequired,
36
+ onInvalid,
37
+ validate,
38
+ } = useInputField({ props, targetInput })
39
+
40
+ const onChange = (e: Event, val: string | number) => {
41
+ modelState.value = val
42
+ validate(e)
43
+ }
33
44
  </script>
34
45
 
35
46
  <template>
36
47
  <fieldset
37
- class="space-y-5"
48
+ class="space-y-4"
38
49
  :aria-labelledby="label ? `${inputID}-legend` : undefined"
39
50
  :aria-describedby="help ? `${inputID}-help` : undefined"
40
51
  >
41
52
  <div v-if="label">
42
- <FieldsetLegend :id="`${inputID}-legend`" :label="label" />
53
+ <FieldsetLegend
54
+ :id="`${inputID}-legend`"
55
+ :label="label"
56
+ :required="isRequired"
57
+ />
43
58
  <InputHelp v-if="help" :id="`${inputID}-help`" tag="p" :text="help" />
44
59
  </div>
45
60
 
61
+ <div v-if="errorState" class="mt-0.5">
62
+ <p class="text-sm text-red-700">{{ errorState }}</p>
63
+ </div>
64
+
46
65
  <div class="flex">
47
66
  <div
48
- class="grid gap-y-5"
67
+ class="grid gap-y-6"
49
68
  :class="{
50
69
  'sm:grid sm:gap-x-5 sm:space-y-0': columns !== undefined,
51
70
  'sm:grid-cols-2': columns === 2,
@@ -57,30 +76,30 @@ const { inputID, isDisabled } = useInputField()
57
76
  :key="option.value"
58
77
  class="flex items-start"
59
78
  >
60
- <div class="flex items-center h-6">
79
+ <div class="flex items-center h-5">
61
80
  <input
62
81
  :id="`${inputID}-${index}`"
82
+ ref="radios"
63
83
  :aria-describedby="
64
84
  option.help ? `${inputID}-${index}-help` : undefined
65
85
  "
66
86
  :aria-labelledby="`${inputID}-${index}-label`"
67
- :checked="modelValue === option.value"
87
+ :checked="modelState === option.value"
68
88
  :class="[
69
- 'h-4 w-4',
70
- 'border-gray-300 text-xy-blue focus:ring-xy-blue-500',
89
+ 'h-4 w-4 cursor-pointer text-xy-blue',
71
90
  'disabled:bg-gray-100 disabled:border-gray-200 disabled:cursor-not-allowed disabled:opacity-100',
72
91
  'checked:disabled:bg-xy-blue checked:disabled:border-xy-blue checked:disabled:opacity-50',
92
+ errorState
93
+ ? 'border-red-700 focus:ring-red-700'
94
+ : 'border-gray-300 focus:ring-xy-blue-500',
73
95
  ]"
74
96
  :disabled="option.disabled"
75
97
  :name="inputID"
76
98
  type="radio"
77
99
  :value="option.value"
78
- v-bind="{
79
- onChange: () => {
80
- emits('update:modelValue', option.value)
81
- },
82
- ...$attrs,
83
- }"
100
+ v-bind="$attrs"
101
+ @change="onChange($event, option.value)"
102
+ @invalid="onInvalid"
84
103
  />
85
104
  </div>
86
105
  <div class="ml-3">
@@ -88,9 +107,12 @@ const { inputID, isDisabled } = useInputField()
88
107
  :id="`${inputID}-${index}-label`"
89
108
  :for="`${inputID}-${index}`"
90
109
  :label="option.label"
91
- :class="(isDisabled || option.disabled) && 'cursor-not-allowed'"
110
+ :class="
111
+ isDisabled || option.disabled
112
+ ? 'cursor-not-allowed'
113
+ : 'cursor-pointer'
114
+ "
92
115
  />
93
-
94
116
  <InputHelp :id="`${inputID}-${index}-help`" :text="option.help" />
95
117
  </div>
96
118
  </div>
@@ -1,4 +1,4 @@
1
- <script setup lang="ts">
1
+ <script setup lang="ts" generic="T extends InputOption">
2
2
  import {
3
3
  RadioGroup,
4
4
  RadioGroupDescription,
@@ -6,11 +6,16 @@ import {
6
6
  RadioGroupOption,
7
7
  } from "@headlessui/vue"
8
8
  import { CheckCircleIcon } from "@heroicons/vue/solid"
9
- import { computed, ref } from "vue"
10
9
  import InputLabel from "./InputLabel.vue"
11
10
  import InputHelp from "./InputHelp.vue"
12
11
  import FieldsetLegend from "./FieldsetLegend.vue"
13
- import { useInputField } from "@/composables/forms"
12
+ import { defaultInputProps, useInputField } from "@/composables/forms"
13
+ import type {
14
+ ColumnedInput,
15
+ InputOption,
16
+ OptionsInput,
17
+ } from "@/composables/forms"
18
+ import { computed, ref } from "vue"
14
19
 
15
20
  defineOptions({
16
21
  inheritAttrs: false,
@@ -20,83 +25,63 @@ defineOptions({
20
25
  * NOTE (spk) headless UI introduced a "name" prop that includes a hidden field
21
26
  * to use the modelValue inside of forms. It does not however resolve the issue of
22
27
  * supporting HTML5 form validation, so we'll add our own hidden radio buttons to support both.
23
- *
24
- * The headless technique does include supporting complex modelValues such as objects, which we may
25
- * need in the future. We can revist required validation at that time using a singular hidden checkbox.
26
28
  */
27
29
 
28
- type ModelValue = string | number
29
-
30
- type RadioCard = {
31
- disabled?: boolean
32
- help?: string
33
- label: string
34
- sublabel?: string
35
- value: ModelValue
30
+ interface RadioCards extends OptionsInput {
31
+ options: T[]
36
32
  }
37
33
 
38
34
  const props = withDefaults(
39
- defineProps<{
40
- columns?: 2 | 3
41
- help?: string
42
- label?: string
43
- modelValue?: ModelValue
44
- options: RadioCard[]
45
- }>(),
46
- {
47
- columns: undefined,
48
- help: "",
49
- label: "",
50
- modelValue: undefined,
51
- }
35
+ defineProps<RadioCards & ColumnedInput>(),
36
+ defaultInputProps
52
37
  )
53
38
 
54
- const emit = defineEmits<{
55
- (e: "update:modelValue", modelValue: ModelValue): void
56
- }>()
57
-
58
- const { inputID, isDisabled, isRequired, nameAttr } = useInputField()
59
-
60
- // tracking internal state separate from modelValue
61
- // allows v-model to be undefined by the consumer but still supports
62
- // the display requirements of the component.
63
- // this is usful when the component is used inside a form element and
64
- // tracking v-model isn't required.
65
- const internalState = ref()
66
- const invalid = ref<boolean>()
67
- const checkedState = computed(() => {
68
- if (props.modelValue === undefined) {
69
- return internalState.value
39
+ defineEmits(["update:modelValue", "update:error"])
40
+ const hiddenRadios = ref<HTMLInputElement[]>([])
41
+ // there are multiple radio buttons that could be the target
42
+ // for validation set to the first input
43
+ const targetInput = computed(() => {
44
+ if (hiddenRadios.value.length === 0) {
45
+ return null
70
46
  }
71
47
 
72
- return props.modelValue
48
+ return hiddenRadios.value[0]
73
49
  })
74
-
75
- const onChange = (val: ModelValue) => {
76
- internalState.value = val
77
- invalid.value = false
78
- emit("update:modelValue", val)
50
+ const {
51
+ inputID,
52
+ isDisabled,
53
+ isRequired,
54
+ nameAttr,
55
+ modelState,
56
+ errorState,
57
+ onInvalid,
58
+ } = useInputField({ props, targetInput })
59
+
60
+ const onUpdate = (val: unknown) => {
61
+ if (val) {
62
+ errorState.value = ""
63
+ }
79
64
  }
80
65
  </script>
81
66
 
82
67
  <template>
83
68
  <RadioGroup
84
- :model-value="checkedState"
69
+ v-model="modelState"
85
70
  :disabled="isDisabled"
86
- :aria-invalid="invalid === true ? 'true' : null"
87
- :aria-errormessage="invalid === true ? `error-${inputID}` : null"
88
- @update:model-value="onChange"
71
+ :aria-invalid="errorState ? 'true' : null"
72
+ :aria-errormessage="errorState ? `error-${inputID}` : null"
73
+ @update:model-value="onUpdate"
89
74
  >
90
75
  <RadioGroupLabel v-if="label" class="block">
91
- <FieldsetLegend tag="div" :label="label" />
76
+ <FieldsetLegend tag="div" :label="label" :required="isRequired" />
92
77
  </RadioGroupLabel>
93
78
 
94
79
  <RadioGroupDescription v-if="help">
95
80
  <InputHelp :text="help" />
96
81
  </RadioGroupDescription>
97
82
 
98
- <div v-if="invalid === true" :id="`error-${inputID}`" class="sr-only">
99
- Please select one of these options.
83
+ <div v-if="errorState" :id="`error-${inputID}`">
84
+ <p class="text-sm text-red-700">{{ errorState }}</p>
100
85
  </div>
101
86
 
102
87
  <div
@@ -128,6 +113,7 @@ const onChange = (val: ModelValue) => {
128
113
  disabled
129
114
  ? 'cursor-not-allowed bg-gray-50 border-gray-200 opacity-90'
130
115
  : 'cursor-pointer bg-white border-gray-300',
116
+ errorState && !disabled ? 'border-red-700' : '',
131
117
  checked ? 'border-transparent' : '',
132
118
  active ? 'border-xy-blue ring-2 ring-xy-blue-500' : '',
133
119
  ]"
@@ -179,7 +165,9 @@ const onChange = (val: ModelValue) => {
179
165
  aria-hidden="true"
180
166
  />
181
167
 
168
+ <!--TODO: (spk) ideally this would trigger a change event -->
182
169
  <input
170
+ ref="hiddenRadios"
183
171
  class="sr-only top-1 left-1"
184
172
  aria-hidden="true"
185
173
  :checked="checked"
@@ -188,7 +176,7 @@ const onChange = (val: ModelValue) => {
188
176
  tabindex="-1"
189
177
  type="radio"
190
178
  :value="option.value"
191
- @invalid="invalid = true"
179
+ @invalid="onInvalid"
192
180
  />
193
181
  </div>
194
182
  </RadioGroupOption>
@@ -1,71 +1,68 @@
1
1
  <script setup lang="ts">
2
2
  import InputLabel from "./InputLabel.vue"
3
3
  import InputHelp from "./InputHelp.vue"
4
- import { useInputField } from "@/composables/forms"
4
+ import { defaultInputProps, useInputField } from "@/composables/forms"
5
+ import type { OptionsInput } from "@/composables/forms"
6
+ import { ref } from "vue"
5
7
 
6
8
  defineOptions({
7
9
  inheritAttrs: false,
8
10
  })
9
11
 
10
- withDefaults(
11
- defineProps<{
12
- label?: string
13
- help?: string
14
- placeholder?: string
15
- options: { label: string; value: string | number }[]
16
- modelValue: string | number | undefined
17
- }>(),
18
- {
19
- label: "",
20
- help: "",
21
- placeholder: "Select an option",
22
- }
23
- )
12
+ const props = withDefaults(defineProps<OptionsInput>(), {
13
+ ...defaultInputProps,
14
+ placeholder: "Select an option",
15
+ })
16
+
17
+ defineEmits(["update:modelValue", "update:error"])
18
+ const targetInput = ref<HTMLInputElement | null>(null)
19
+ const { inputID, isRequired, validate, modelState, errorState, onInvalid } =
20
+ useInputField({ props, targetInput })
24
21
 
25
- const emit = defineEmits(["update:modelValue"])
26
- const { inputID, isValid } = useInputField()
22
+ const onChange = (e: Event) => {
23
+ modelState.value = (e.target as HTMLInputElement).value
24
+ validate(e)
25
+ }
27
26
  </script>
28
27
 
29
28
  <template>
30
29
  <div>
31
- <div class="mb-1">
32
- <InputLabel :id="`${inputID}-label`" :for="inputID" :label="label" />
33
- </div>
30
+ <InputLabel
31
+ :id="`${inputID}-label`"
32
+ class="mb-2"
33
+ :for="inputID"
34
+ :label="label"
35
+ :required="isRequired"
36
+ />
34
37
  <select
35
38
  :id="inputID"
39
+ ref="targetInput"
36
40
  :aria-labelledby="label ? `${inputID}-label` : undefined"
37
41
  :aria-describedby="help ? `${inputID}-help` : undefined"
38
42
  :class="[
39
43
  'block w-full rounded-md border-0 py-2 shadow-sm ring-1 ring-inset focus:ring-2 sm:text-sm sm:leading-6 pl-3 pr-10',
40
- 'disabled:cursor-not-allowed disabled:bg-gray-50 disabled:text-gray-600 disabled:ring-gray-200 disabled:opacity-100',
41
- isValid
42
- ? 'text-gray-800 ring-gray-300 placeholder:text-gray-400 focus:ring-xy-blue-500'
43
- : 'text-red-900 ring-red-700 placeholder:text-red-300 focus:ring-red-700',
44
+ 'disabled:cursor-not-allowed disabled:bg-gray-50 disabled:text-gray-700 disabled:ring-gray-200 disabled:opacity-100',
45
+ errorState
46
+ ? 'text-red-900 ring-red-700 placeholder:text-red-300 focus:ring-red-700'
47
+ : 'text-gray-900 ring-gray-300 placeholder:text-gray-400 focus:ring-xy-blue-500',
44
48
  ]"
45
- :value="modelValue"
46
- v-bind="{
47
- ...$attrs,
48
- onChange: ($event) => {
49
- emit('update:modelValue', ($event.target as HTMLInputElement).value)
50
- },
51
- }"
49
+ :value="modelState"
50
+ v-bind="$attrs"
51
+ @change="onChange"
52
+ @invalid="onInvalid"
52
53
  >
53
- <option
54
- v-if="placeholder"
55
- value=""
56
- disabled
57
- selected
58
- v-text="placeholder"
59
- />
54
+ <option value="" disabled selected v-text="placeholder" />
60
55
  <option
61
56
  v-for="option in options"
62
57
  :key="option.value"
63
58
  :value="option.value"
59
+ :disabled="option.disabled"
64
60
  v-text="option.label"
65
61
  />
66
62
  </select>
67
- <div class="mt-1">
68
- <InputHelp :id="`${inputID}-help`" :text="help" />
63
+ <InputHelp :id="`${inputID}-help`" class="mt-1" :text="help" />
64
+ <div v-if="errorState" class="mt-0.5">
65
+ <p class="text-sm text-red-700">{{ errorState }}</p>
69
66
  </div>
70
67
  </div>
71
68
  </template>
@@ -1,53 +1,61 @@
1
1
  <script setup lang="ts">
2
2
  import InputLabel from "./InputLabel.vue"
3
3
  import InputHelp from "./InputHelp.vue"
4
- import { useInputField } from "@/composables/forms"
4
+ import { useInputField, defaultInputProps } from "@/composables/forms"
5
+ import type { TextareaInput } from "@/composables/forms"
6
+ import { ref } from "vue"
5
7
 
6
8
  defineOptions({
7
9
  inheritAttrs: false,
8
10
  })
9
11
 
10
- withDefaults(
11
- defineProps<{
12
- help?: string
13
- label?: string
14
- modelValue?: string | number
15
- }>(),
16
- {
17
- help: "",
18
- label: "",
19
- modelValue: "",
20
- }
21
- )
12
+ const props = withDefaults(defineProps<TextareaInput>(), defaultInputProps)
13
+ defineEmits(["update:modelValue", "update:error"])
14
+ const targetInput = ref<HTMLInputElement | null>(null)
15
+ const {
16
+ inputID,
17
+ isRequired,
18
+ modelState,
19
+ errorState,
20
+ onInvalid,
21
+ inputValidation,
22
+ } = useInputField({ props, targetInput })
22
23
 
23
- const emit = defineEmits(["update:modelValue"])
24
- const { inputID, isValid } = useInputField()
24
+ const onInput = (e: Event) => {
25
+ modelState.value = (e.target as HTMLInputElement).value
26
+ inputValidation(e)
27
+ }
25
28
  </script>
26
29
 
27
30
  <template>
28
31
  <div>
29
- <div class="mb-1">
30
- <InputLabel :id="`${inputID}-label`" :for="inputID" :label="label" />
31
- </div>
32
+ <InputLabel
33
+ :id="`${inputID}-label`"
34
+ class="mb-2"
35
+ :for="inputID"
36
+ :label="label"
37
+ :required="isRequired"
38
+ />
32
39
  <textarea
33
40
  :id="inputID"
41
+ ref="targetInput"
34
42
  :aria-labelledby="label ? `${inputID}-label` : undefined"
35
43
  :aria-describedby="help ? `${inputID}-help` : undefined"
36
44
  :class="[
37
45
  'block w-full rounded-md border-0 py-2 shadow-sm ring-1 ring-inset focus:ring-2 sm:text-sm sm:leading-6',
38
- 'disabled:cursor-not-allowed disabled:bg-gray-50 disabled:text-gray-600 disabled:ring-gray-200',
39
- isValid
40
- ? 'text-gray-800 ring-gray-300 placeholder:text-gray-400 focus:ring-xy-blue-500'
41
- : 'text-red-900 ring-red-700 placeholder:text-red-300 focus:ring-red-700',
46
+ 'disabled:cursor-not-allowed disabled:bg-gray-50 disabled:text-gray-700 disabled:ring-gray-200',
47
+ errorState
48
+ ? 'text-red-900 ring-red-700 placeholder:text-red-300 focus:ring-red-700'
49
+ : 'text-gray-900 ring-gray-300 placeholder:text-gray-400 focus:ring-xy-blue-500',
42
50
  ]"
43
- :value="modelValue"
51
+ :value="modelState || undefined"
44
52
  v-bind="$attrs"
45
- @input="
46
- emit('update:modelValue', ($event.target as HTMLInputElement).value)
47
- "
53
+ @input="onInput"
54
+ @invalid="onInvalid"
48
55
  />
49
- <div class="mt-1">
50
- <InputHelp :id="`${inputID}-help`" :text="help"></InputHelp>
56
+ <InputHelp :id="`${inputID}-help`" class="mb-1" :text="help"></InputHelp>
57
+ <div v-if="errorState" class="mt-0.5">
58
+ <p class="text-sm text-red-700">{{ errorState }}</p>
51
59
  </div>
52
60
  </div>
53
61
  </template>
@@ -7,7 +7,8 @@ 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 { useInputField } from "@/composables/forms"
10
+ import { hasAttribute } from "@/composables/forms"
11
+ import { computed, useAttrs } from "vue"
11
12
 
12
13
  defineOptions({
13
14
  inheritAttrs: false,
@@ -15,19 +16,21 @@ defineOptions({
15
16
 
16
17
  withDefaults(
17
18
  defineProps<{
18
- modelValue?: boolean | undefined
19
+ modelValue?: boolean
19
20
  label?: string
20
21
  help?: string
21
22
  }>(),
22
23
  {
23
- modelValue: undefined,
24
24
  label: "",
25
25
  help: "",
26
26
  }
27
27
  )
28
28
 
29
29
  const emits = defineEmits(["update:modelValue"])
30
- const { isDisabled } = useInputField()
30
+ const attrs = useAttrs()
31
+ const isDisabled = computed(() => {
32
+ return hasAttribute(attrs, "disabled")
33
+ })
31
34
  </script>
32
35
  <template>
33
36
  <SwitchGroup as="div" class="flex items-start">
@@ -51,11 +54,11 @@ const { isDisabled } = useInputField()
51
54
  />
52
55
  </Switch>
53
56
 
54
- <div class="ml-3">
57
+ <div class="ml-3 mt-0.5">
55
58
  <SwitchLabel v-if="label">
56
59
  <InputLabel
57
60
  :label="label"
58
- :class="isDisabled && 'cursor-not-allowed'"
61
+ :class="isDisabled ? 'cursor-not-allowed' : 'cursor-pointer'"
59
62
  />
60
63
  </SwitchLabel>
61
64