@xy-planning-network/trees 0.15.2 → 0.15.3

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 (53) hide show
  1. package/dist/trees.es.js +17051 -12088
  2. package/dist/trees.umd.js +81 -13
  3. package/package.json +3 -2
  4. package/src/index.css +10 -0
  5. package/src/lib-components/forms/Combobox.vue +240 -0
  6. package/src/lib-components/forms/FileUpload.vue +596 -0
  7. package/src/lib-components/forms/FormCell.vue +52 -0
  8. package/src/lib-components/forms/FormDisplay.vue +96 -0
  9. package/src/lib-components/forms/FormGrid.vue +23 -0
  10. package/src/lib-components/forms/FormSection.vue +57 -0
  11. package/src/lib-components/forms/InputDisplay.vue +36 -0
  12. package/src/lib-components/forms/InputHelp.vue +9 -2
  13. package/src/lib-components/forms/MultiSelect.vue +404 -0
  14. package/src/lib-components/forms/RadioCards.vue +14 -1
  15. package/src/lib-components/forms/RepeaterDisplay.vue +214 -0
  16. package/src/lib-components/indicators/DismissableBadge.vue +31 -0
  17. package/types/composables/badge.d.ts +8 -0
  18. package/types/composables/forms.d.ts +22 -0
  19. package/types/composables/http.d.ts +8 -0
  20. package/types/composables/index.d.ts +4 -0
  21. package/types/composables/useFieldsSchema.d.ts +115 -0
  22. package/types/composables/useInlineMarkdown.d.ts +20 -0
  23. package/types/composables/useRepeater.d.ts +116 -0
  24. package/types/entry.d.ts +2 -1
  25. package/types/helpers/Bytes.d.ts +14 -0
  26. package/types/helpers/GetProperty.d.ts +21 -0
  27. package/types/helpers/SetProperty.d.ts +18 -0
  28. package/types/lib-components/forms/BaseInput.vue.d.ts +1 -1
  29. package/types/lib-components/forms/Checkbox.vue.d.ts +1 -1
  30. package/types/lib-components/forms/Combobox.vue.d.ts +16 -0
  31. package/types/lib-components/forms/DateRangePicker.vue.d.ts +3 -3
  32. package/types/lib-components/forms/DateTimeInput.vue.d.ts +1 -1
  33. package/types/lib-components/forms/FileUpload.vue.d.ts +19 -0
  34. package/types/lib-components/forms/FormCell.vue.d.ts +15 -0
  35. package/types/lib-components/forms/FormDisplay.vue.d.ts +30 -0
  36. package/types/lib-components/forms/FormGrid.vue.d.ts +19 -0
  37. package/types/lib-components/forms/FormSection.vue.d.ts +16 -0
  38. package/types/lib-components/forms/InputDisplay.vue.d.ts +14 -0
  39. package/types/lib-components/forms/MultiCheckboxes.vue.d.ts +1 -1
  40. package/types/lib-components/forms/MultiSelect.vue.d.ts +22 -0
  41. package/types/lib-components/forms/NumberInput.vue.d.ts +3 -3
  42. package/types/lib-components/forms/Radio.vue.d.ts +1 -1
  43. package/types/lib-components/forms/RadioCards.vue.d.ts +3 -0
  44. package/types/lib-components/forms/RangeCalendar.vue.d.ts +1 -1
  45. package/types/lib-components/forms/RepeaterDisplay.vue.d.ts +29 -0
  46. package/types/lib-components/forms/Select.vue.d.ts +1 -1
  47. package/types/lib-components/forms/TextArea.vue.d.ts +1 -1
  48. package/types/lib-components/forms/YesOrNoRadio.vue.d.ts +1 -1
  49. package/types/lib-components/index.d.ts +54 -89
  50. package/types/lib-components/indicators/DismissableBadge.vue.d.ts +13 -0
  51. package/types/lib-components/overlays/ContentModal.vue.d.ts +1 -1
  52. package/types/lib-components/overlays/Modal.vue.d.ts +1 -1
  53. package/types/lib-components/overlays/Slideover.vue.d.ts +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xy-planning-network/trees",
3
- "version": "0.15.2",
3
+ "version": "0.15.3",
4
4
  "description": "",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -62,12 +62,13 @@
62
62
  },
63
63
  "dependencies": {
64
64
  "@floating-ui/vue": "^1.0.1",
65
- "@headlessui/vue": "^1.4.2",
65
+ "@headlessui/vue": "^1.7.23",
66
66
  "@heroicons/vue": "^2.2.0",
67
67
  "@maskito/core": "^3.5.0",
68
68
  "@maskito/kit": "^3.5.0",
69
69
  "@maskito/vue": "^3.5.0",
70
70
  "axios": "^1.19.0",
71
+ "marked": "^18.0.14",
71
72
  "reka-ui": "^2.9.9"
72
73
  },
73
74
  "peerDependencies": {
package/src/index.css CHANGED
@@ -183,6 +183,11 @@
183
183
  @apply inline-flex justify-center items-center py-2.5 border-b-2 border-b-red-700 text-base font-display font-semibold shadow-none text-neutral-800 hover:text-red-700 hover:border-b-transparent focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-xy-blue-500 disabled:text-neutral-800 disabled:border-b-red-700 disabled:opacity-70 disabled:cursor-not-allowed transition-colors ease-linear duration-150;
184
184
  }
185
185
 
186
+ /* Combobox */
187
+ .xy-combobox .xy-combobox-input {
188
+ @apply shadow-none border-none bg-transparent focus:ring-0 p-0;
189
+ }
190
+
186
191
  /* Header classes */
187
192
  .h1 {
188
193
  @apply text-3xl leading-9 font-semibold;
@@ -229,6 +234,11 @@
229
234
  @apply font-medium border-b-2 border-b-xy-blue hover:border-b-transparent hover:text-xy-blue;
230
235
  }
231
236
 
237
+ /* MultiSelect */
238
+ .xy-multiselect .xy-multiselect-input {
239
+ @apply shadow-none border-none bg-transparent focus:ring-0 p-0;
240
+ }
241
+
232
242
  /* RangeCalendar */
233
243
 
234
244
  /* Calendar Prev/Next navigation */
@@ -0,0 +1,240 @@
1
+ <script setup lang="ts">
2
+ import { computed, ref } from "vue"
3
+ import {
4
+ Combobox,
5
+ ComboboxButton,
6
+ ComboboxInput,
7
+ ComboboxLabel,
8
+ ComboboxOption,
9
+ ComboboxOptions,
10
+ } from "@headlessui/vue"
11
+ import { CheckIcon, ChevronUpDownIcon } from "@heroicons/vue/solid"
12
+ import { useInputField, type OptionsInput } from "@/composables/forms"
13
+ import InputHelp from "@/lib-components/forms/InputHelp.vue"
14
+ import InputError from "@/lib-components/forms/InputError.vue"
15
+ import InputLabel from "@/lib-components/forms/InputLabel.vue"
16
+
17
+ // NOTE(spk): What this doesn't do:
18
+ //
19
+ // - allow "custom-values" i.e. user supplied values
20
+ // - support async options based on query
21
+ // - limited support for HTML5 input events
22
+ // - grouped options
23
+ // - no deselection - it works like a <select />, but is searchable
24
+
25
+ defineOptions({
26
+ inheritAttrs: false,
27
+ })
28
+
29
+ const props = withDefaults(defineProps<OptionsInput>(), {
30
+ help: "",
31
+ label: "",
32
+ modelValue: undefined,
33
+ placeholder: "Select an option",
34
+ })
35
+
36
+ const modelState = defineModel<OptionsInput["modelValue"]>({
37
+ default: null,
38
+ required: false,
39
+ })
40
+
41
+ const {
42
+ aria,
43
+ errorState,
44
+ inputID,
45
+ isDisabled,
46
+ isRequired,
47
+ nameAttr,
48
+ onInvalid,
49
+ validate,
50
+ } = useInputField(props)
51
+
52
+ const maxOptions = 50
53
+
54
+ const query = ref("")
55
+
56
+ const filteredOptions = computed(() => {
57
+ return query.value === ""
58
+ ? props.options
59
+ : props.options.filter((opt) => {
60
+ return (
61
+ opt.label?.toLowerCase().includes(query.value.toLowerCase()) ||
62
+ opt.help?.toLowerCase().includes(query.value.toLowerCase())
63
+ )
64
+ })
65
+ })
66
+
67
+ const renderableOptions = computed(() => {
68
+ return filteredOptions.value.slice(0, maxOptions)
69
+ })
70
+
71
+ const totalOptions = computed(() => {
72
+ return filteredOptions.value.length
73
+ })
74
+
75
+ const selectedOption = computed(() => {
76
+ return props.options.find((opt) => {
77
+ return opt.value === modelState.value
78
+ })
79
+ })
80
+
81
+ const isPaginated = computed(() => {
82
+ return totalOptions.value > maxOptions
83
+ })
84
+
85
+ const onUpdate = (val: unknown) => {
86
+ if (val) {
87
+ query.value = ""
88
+ errorState.value = ""
89
+ }
90
+ }
91
+
92
+ // NOTE(spk): when @headlessui/Combobox is not in multiple mode mousedown
93
+ // events that bubble outside the parent are picked up
94
+ // by the "outside click" event that closes active modals.
95
+ // It's not expected that this event should need to be captured
96
+ // outside the component - @mousedown.stop prevents the event from
97
+ // bubbling outside the parent.
98
+ </script>
99
+
100
+ <template>
101
+ <div class="xy-combobox relative" @mousedown.stop>
102
+ <Combobox
103
+ v-model="modelState"
104
+ as="div"
105
+ :disabled="isDisabled"
106
+ :name="nameAttr"
107
+ @update:model-value="onUpdate"
108
+ >
109
+ <ComboboxLabel
110
+ v-if="label"
111
+ :id="aria.labelledby"
112
+ :as="InputLabel"
113
+ class="mb-2"
114
+ :label="label"
115
+ :required="isRequired"
116
+ />
117
+
118
+ <div
119
+ :class="[
120
+ 'relative w-full rounded-md border-0 py-2 pl-3 pr-1.5 shadow-sm ring-1 ring-inset has-[input:focus]:ring-2',
121
+ 'has-[input:disabled]:cursor-not-allowed has-[input:disabled]:bg-gray-50 has-[input:disabled]:text-gray-700 has-[input:disabled]:ring-gray-200',
122
+ errorState
123
+ ? 'text-red-900 ring-red-700 has-[input:focus]:ring-red-700'
124
+ : 'text-gray-900 ring-gray-300 has-[input:focus]:ring-xy-blue-500',
125
+ ]"
126
+ >
127
+ <div class="pr-10">
128
+ <ComboboxButton as="div" class="leading-none" aria-hidden>
129
+ <ComboboxInput
130
+ :id="inputID"
131
+ :aria-labelledby="aria.labelledby"
132
+ :aria-describedby="aria.describedby"
133
+ :aria-errormessage="aria.errormessage"
134
+ :class="[
135
+ 'xy-combobox-input truncate w-full sm:text-sm sm:leading-6',
136
+ errorState
137
+ ? 'placeholder:text-red-300'
138
+ : 'placeholder:text-gray-400',
139
+ ]"
140
+ :disabled="isDisabled"
141
+ :display-value="() => selectedOption?.label || ''"
142
+ :placeholder="placeholder"
143
+ @change="query = $event.target.value"
144
+ />
145
+ </ComboboxButton>
146
+ </div>
147
+
148
+ <ComboboxButton
149
+ class="absolute inset-y-0 right-0 flex items-center px-2 focus:outline-none"
150
+ >
151
+ <ChevronUpDownIcon class="h-5 w-5 text-gray-500" aria-hidden="true" />
152
+ </ComboboxButton>
153
+ </div>
154
+
155
+ <ComboboxOptions
156
+ class="absolute z-[5] mt-1 max-h-60 w-full overflow-auto rounded-md bg-white text-base shadow-lg ring-1 ring-black/5 focus:outline-none sm:text-sm scroll-pt-10"
157
+ >
158
+ <li
159
+ v-if="isPaginated"
160
+ class="bg-neutral-100 font-medium border-b border-neutral-200 sticky top-0 py-1.5 px-3 z-[5]"
161
+ >
162
+ Showing {{ renderableOptions.length }} of {{ totalOptions }} results.
163
+ </li>
164
+
165
+ <ComboboxOption
166
+ v-for="option in renderableOptions"
167
+ v-slot="{
168
+ active,
169
+ disabled,
170
+ selected,
171
+ }: {
172
+ active: boolean
173
+ disabled: boolean
174
+ selected: boolean
175
+ }"
176
+ :key="option.value"
177
+ :value="option.value"
178
+ :disabled="isDisabled || option.disabled"
179
+ >
180
+ <div
181
+ :class="[
182
+ 'relative select-none py-2 pl-8 pr-4',
183
+ active ? 'text-gray-900 bg-neutral-50 outline-none' : '',
184
+ disabled ? 'text-gray-500 cursor-not-allowed' : 'cursor-pointer',
185
+ ]"
186
+ >
187
+ <div>
188
+ <div
189
+ :class="[
190
+ 'block truncate',
191
+ selected ? 'font-semibold' : 'font-medium',
192
+ ]"
193
+ >
194
+ {{ option.label }}
195
+ </div>
196
+ <div v-if="option.help" class="block truncate">
197
+ {{ option.help }}
198
+ </div>
199
+ </div>
200
+
201
+ <span
202
+ v-if="selected"
203
+ class="absolute inset-y-0 left-0 flex items-center pl-1.5 text-xy-blue-500"
204
+ >
205
+ <CheckIcon class="h-5 w-5" aria-hidden="true" />
206
+ </span>
207
+ </div>
208
+ </ComboboxOption>
209
+ </ComboboxOptions>
210
+ </Combobox>
211
+
212
+ <InputHelp
213
+ v-if="help"
214
+ :id="aria.describedby"
215
+ class="mt-1"
216
+ tag="p"
217
+ :text="help"
218
+ />
219
+
220
+ <InputError :id="aria.errormessage" class="mt-1" :text="errorState" />
221
+
222
+ <!--Hidden input for validation-->
223
+ <select
224
+ v-model="modelState"
225
+ aria-hidden
226
+ class="sr-only top-1 left-1"
227
+ :disabled="isDisabled"
228
+ :required="isRequired"
229
+ :tabindex="errorState ? undefined : -1"
230
+ @change="validate"
231
+ @invalid="onInvalid"
232
+ >
233
+ <option
234
+ v-for="option in options"
235
+ :key="option.value"
236
+ :value="option.value"
237
+ />
238
+ </select>
239
+ </div>
240
+ </template>