@xy-planning-network/trees 0.4.8 → 0.4.9-rc-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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xy-planning-network/trees",
3
- "version": "0.4.8",
3
+ "version": "0.4.9-rc-3",
4
4
  "description": "",
5
5
  "license": "MIT",
6
6
  "repository": "github:xy-planning-network/trees",
@@ -1,14 +1,23 @@
1
1
  <script setup lang="ts">
2
2
  import { hasSlotContent } from "@/helpers/Slots"
3
+ withDefaults(
4
+ defineProps<{
5
+ tag?: string
6
+ }>(),
7
+ {
8
+ tag: "legend",
9
+ }
10
+ )
3
11
  </script>
4
12
  <template>
5
- <legend
13
+ <component
14
+ :is="tag"
6
15
  v-if="hasSlotContent($slots.default)"
7
16
  v-bind="{
8
17
  ...$attrs,
9
- class: 'text-base font-medium leading-tight text-gray-900',
18
+ class: 'text-sm font-semibold leading-snug text-gray-900',
10
19
  }"
11
20
  >
12
21
  <slot />
13
- </legend>
22
+ </component>
14
23
  </template>
@@ -46,7 +46,7 @@ const hasLegend = computed(() => {
46
46
  </FieldsetLegend>
47
47
  <InputHelp tag="p" :text="help" :id="`${uuid}-help`" />
48
48
  </div>
49
- <div class="">
49
+ <div class="flex">
50
50
  <div
51
51
  class="grid gap-4"
52
52
  :class="{
@@ -0,0 +1,183 @@
1
+ <script setup lang="ts">
2
+ import Uniques from "@/helpers/Uniques"
3
+ import {
4
+ RadioGroup,
5
+ RadioGroupDescription,
6
+ RadioGroupLabel,
7
+ RadioGroupOption,
8
+ } from "@headlessui/vue"
9
+ import { CheckCircleIcon } from "@heroicons/vue/solid"
10
+ import { computed, ref, useAttrs } from "vue"
11
+ import InputLabel from "./InputLabel.vue"
12
+ import InputHelp from "./InputHelp.vue"
13
+ import FieldsetLegend from "./FieldsetLegend.vue"
14
+
15
+ /*
16
+ * NOTE (spk) headless UI introduced a "name" prop that includes a hidden field
17
+ * to use the modelValue inside of forms. It does not however resolve the issue of
18
+ * supporting HTML5 form validation, so we'll add our own hidden radio buttons to support both.
19
+ *
20
+ * The headless technique does include supporting complex modelValues such as objects, which we may
21
+ * need in the future. We can revist required validation at that time using a singular hidden checkbox.
22
+ */
23
+
24
+ type ModelValue = string | number
25
+
26
+ type RadioCard = {
27
+ disabled?: boolean
28
+ help?: string
29
+ label: string
30
+ sublabel?: string
31
+ value: ModelValue
32
+ }
33
+
34
+ const props = withDefaults(
35
+ defineProps<{
36
+ columns?: 2 | 3
37
+ help?: string
38
+ legend?: string
39
+ modelValue?: ModelValue
40
+ options: RadioCard[]
41
+ }>(),
42
+ {
43
+ columns: undefined,
44
+ help: "",
45
+ legend: "",
46
+ modelValue: undefined,
47
+ }
48
+ )
49
+
50
+ const emit = defineEmits<{
51
+ (e: "update:modelValue", modelValue: ModelValue): void
52
+ }>()
53
+
54
+ const attrs = useAttrs()
55
+ const uuid = (attrs.id as string) || Uniques.CreateIdAttribute()
56
+
57
+ // tracking internal state separate from modelValue
58
+ // allows v-model to be undefined by the consumer but still supports
59
+ // the display requirements of the component.
60
+ // this is usful when the component is used inside a form element and
61
+ // tracking v-model isn't required.
62
+ const internalState = ref()
63
+ const invalid = ref<boolean>()
64
+ const checked = computed(() => {
65
+ if (props.modelValue === undefined) {
66
+ return internalState.value
67
+ }
68
+
69
+ return props.modelValue
70
+ })
71
+
72
+ const onChange = (val: ModelValue) => {
73
+ internalState.value = val
74
+ invalid.value = false
75
+ emit("update:modelValue", val)
76
+ }
77
+
78
+ const nameAttr = computed(() => {
79
+ return typeof attrs.name === "string" && attrs.name !== "" ? attrs.name : uuid
80
+ })
81
+ </script>
82
+
83
+ <template>
84
+ <RadioGroup
85
+ :modelValue="checked"
86
+ @update:model-value="onChange"
87
+ :disabled="typeof attrs.disabled === 'boolean' ? attrs.disabled : false"
88
+ :aria-invalid="invalid === true ? 'true' : null"
89
+ :aria-errormessage="invalid === true ? `error-${uuid}` : null"
90
+ >
91
+ <RadioGroupLabel v-if="legend" class="block">
92
+ <FieldsetLegend tag="div">{{ legend }}</FieldsetLegend>
93
+ </RadioGroupLabel>
94
+ <RadioGroupDescription v-if="help">
95
+ <InputHelp :text="help" />
96
+ </RadioGroupDescription>
97
+ <div v-if="invalid === true" :id="`error-${uuid}`" class="sr-only">
98
+ Please select one of these options.
99
+ </div>
100
+
101
+ <div
102
+ class="mt-4 grid grid-cols-1 gap-y-5 gap-x-4 relative"
103
+ :class="{
104
+ 'sm:grid-cols-2': columns === 2,
105
+ 'sm:grid-cols-3': columns === 3,
106
+ }"
107
+ >
108
+ <RadioGroupOption
109
+ as="template"
110
+ v-for="option in options"
111
+ :disabled="option?.disabled ? option.disabled : false"
112
+ :key="option.value"
113
+ :value="option.value"
114
+ v-slot="{ active, checked, disabled }"
115
+ >
116
+ <div
117
+ :class="[
118
+ checked ? 'border-transparent' : 'border-gray-300',
119
+ active ? 'border-blue-500 ring-2 ring-blue-500' : '',
120
+ 'relative bg-white border rounded-lg shadow-sm p-4 flex cursor-pointer focus:outline-none',
121
+ disabled ? 'opacity-75' : '',
122
+ ]"
123
+ >
124
+ <div class="flex-1 flex pr-1">
125
+ <div class="flex flex-col">
126
+ <RadioGroupLabel as="div">
127
+ <InputLabel
128
+ tag="div"
129
+ class="mt-auto mb-auto"
130
+ :label="option.label"
131
+ />
132
+ </RadioGroupLabel>
133
+ <RadioGroupDescription v-if="option.help" as="div">
134
+ <InputHelp tag="div" class="mt-auto" :text="option.help" />
135
+ </RadioGroupDescription>
136
+ <div
137
+ v-if="option.sublabel || $slots.sublabel"
138
+ class="mt-auto mb-0"
139
+ >
140
+ <RadioGroupDescription
141
+ as="div"
142
+ class="font-semibold leading-snug mt-4 text-gray-900 text-sm"
143
+ >
144
+ {{ option.sublabel }}
145
+ <slot
146
+ name="sublabel"
147
+ :active="active"
148
+ :checked="checked"
149
+ :disabled="disabled"
150
+ :option="option"
151
+ />
152
+ </RadioGroupDescription>
153
+ </div>
154
+ </div>
155
+ </div>
156
+ <CheckCircleIcon
157
+ :class="[!checked ? 'invisible' : '', 'h-5 w-5 text-blue-600']"
158
+ aria-hidden="true"
159
+ />
160
+ <div
161
+ :class="[
162
+ active ? 'border' : 'border-2',
163
+ checked ? 'border-blue-500' : 'border-transparent',
164
+ 'absolute -inset-px rounded-lg pointer-events-none',
165
+ ]"
166
+ aria-hidden="true"
167
+ />
168
+ <input
169
+ class="sr-only top-1 left-1"
170
+ aria-hidden="true"
171
+ :checked="checked"
172
+ :name="nameAttr"
173
+ :required="attrs.required !== undefined && attrs.required !== false"
174
+ tabindex="-1"
175
+ type="radio"
176
+ :value="option.value"
177
+ @invalid="invalid = true"
178
+ />
179
+ </div>
180
+ </RadioGroupOption>
181
+ </div>
182
+ </RadioGroup>
183
+ </template>
@@ -1,6 +1,6 @@
1
1
  import { AxiosRequestConfig } from "axios";
2
2
  export declare type RequestMethod = "GET" | "get" | "PUT" | "put" | "POST" | "post" | "DELETE" | "delete";
3
- export interface RequestOptions extends AxiosRequestConfig {
3
+ export interface RequestOptions {
4
4
  /**
5
5
  * returns the nested data key inside the AxiosResponse data when true
6
6
  */
@@ -15,10 +15,10 @@ export interface RequestOptions extends AxiosRequestConfig {
15
15
  withDelay?: number;
16
16
  }
17
17
  declare const BaseAPI: {
18
- makeRequest<T = any>(opts: RequestOptions): Promise<T>;
18
+ makeRequest<T = any>(config: AxiosRequestConfig, opts: RequestOptions): Promise<T>;
19
19
  get<T_1 = any>(path: string, opts: RequestOptions, params?: Record<string, unknown> | undefined): Promise<T_1>;
20
20
  delete<T_2 = any>(path: string, opts: RequestOptions): Promise<T_2>;
21
- post<T_3 = any>(path: string, data: Record<string, unknown>, opts: RequestOptions): Promise<T_3>;
22
- put<T_4 = any>(path: string, data: Record<string, unknown>, opts: RequestOptions): Promise<T_4>;
21
+ post<T_3 = any>(path: string, data: Record<string, unknown> | FormData, opts: RequestOptions): Promise<T_3>;
22
+ put<T_4 = any>(path: string, data: Record<string, unknown> | FormData, opts: RequestOptions): Promise<T_4>;
23
23
  };
24
24
  export default BaseAPI;
@@ -51,7 +51,7 @@ export interface UseBaseAPI<T> {
51
51
  * Manually call the axios request
52
52
  * can be used multiple times
53
53
  */
54
- execute: (data?: Record<string, unknown>, opts?: RequestOptions) => Promise<T>;
54
+ execute: (data?: Record<string, unknown> | FormData, opts?: RequestOptions) => Promise<T>;
55
55
  }
56
56
  /**
57
57
  * useBaseAPI is a composable wrapper of BaseAPI
@@ -69,7 +69,7 @@ export default function useBaseAPI<T = any>(path: string, method?: RequestMethod
69
69
  isAborted: Ref<boolean>;
70
70
  hasFetched: Ref<boolean>;
71
71
  abort: () => void;
72
- execute: (data?: Record<string, unknown>, opts?: RequestOptions) => Promise<T>;
72
+ execute: (data?: Record<string, unknown> | FormData, opts?: RequestOptions) => Promise<T>;
73
73
  };
74
74
  /**
75
75
  * useBaseAPIGet is a convenience function for useBaseAPI
@@ -0,0 +1,100 @@
1
+ import { Ref } from "vue";
2
+ /**
3
+ * FlashMessage represents the shape of an on screen notification
4
+ * to a user.
5
+ */
6
+ export interface FlashMessage {
7
+ /**
8
+ * The primary body text of the flash. It supports HTML.
9
+ */
10
+ message: string;
11
+ /**
12
+ * Allow the flash to stay on the screen until the user removes it.
13
+ */
14
+ persistent?: boolean;
15
+ /**
16
+ * Determines the style of the flash.
17
+ */
18
+ type: FlashType;
19
+ }
20
+ /**
21
+ * FlashType is used to set the style of the flash that is displayed.
22
+ */
23
+ export declare type FlashType = "warning" | "error" | "info" | "success";
24
+ /**
25
+ * The FlasherAPI offers a simple set of methods for adding and removing flash messages.
26
+ * The implementor of the FlasherAPI is responsible for determining where flashes are stored.
27
+ */
28
+ export interface FlasherAPI {
29
+ add(flash: FlashMessage): string;
30
+ remove(id: string): void;
31
+ error(msg: string, persistent?: boolean): string;
32
+ info(msg: string, persistent?: boolean): string;
33
+ success(msg: string, persistent?: boolean): string;
34
+ warning(msg: string, persistent?: boolean): string;
35
+ genericError(email?: string, persistent?: boolean): string;
36
+ setConfig(config: FlasherConfig): void;
37
+ }
38
+ /**
39
+ * A storage type for flash management.
40
+ */
41
+ declare type FlashStore = Map<string, FlashMessage>;
42
+ /**
43
+ *
44
+ */
45
+ interface FlasherConfig {
46
+ removeDelay?: number;
47
+ email?: string;
48
+ }
49
+ /**
50
+ * newFlasher implements the FlasherAPI interface on the FlashStore it recieves
51
+ * the flash remove delay and a default email address for generic flashes is configurable
52
+ */
53
+ export declare const newFlasher: (flashStore: FlashStore, flasherConfig?: FlasherConfig | undefined) => {
54
+ add(flash: FlashMessage): string;
55
+ remove(id: string): void;
56
+ flash(flash: FlashMessage): string;
57
+ error(message: string, persistent?: boolean): string;
58
+ info(message: string, persistent?: boolean): string;
59
+ success(message: string, persistent?: boolean): string;
60
+ warning(message: string, persistent?: boolean): string;
61
+ genericError(email?: string, persistent?: boolean): string;
62
+ setConfig: (newConfig: FlasherConfig) => void;
63
+ };
64
+ declare const flasher: {
65
+ add(flash: FlashMessage): string;
66
+ remove(id: string): void;
67
+ flash(flash: FlashMessage): string;
68
+ error(message: string, persistent?: boolean): string;
69
+ info(message: string, persistent?: boolean): string;
70
+ success(message: string, persistent?: boolean): string;
71
+ warning(message: string, persistent?: boolean): string;
72
+ genericError(email?: string, persistent?: boolean): string;
73
+ setConfig: (newConfig: FlasherConfig) => void;
74
+ };
75
+ export default flasher;
76
+ /**
77
+ * useFlashes exposes the module level global flashes and flasher for shared access to
78
+ * the a flash queue when a flashStore isn't provided
79
+ * @returns UseFlashes
80
+ */
81
+ export declare function useFlashes(flashStore?: Ref<FlashStore>): {
82
+ flasher: {
83
+ add(flash: FlashMessage): string;
84
+ remove(id: string): void;
85
+ flash(flash: FlashMessage): string;
86
+ error(message: string, persistent?: boolean): string;
87
+ info(message: string, persistent?: boolean): string;
88
+ success(message: string, persistent?: boolean): string;
89
+ warning(message: string, persistent?: boolean): string;
90
+ genericError(email?: string, persistent?: boolean): string;
91
+ setConfig: (newConfig: FlasherConfig) => void;
92
+ };
93
+ flashes: Ref<Map<string, FlashMessage>>;
94
+ };
95
+ /**
96
+ * A helper method to load any flashes on the global Window.Flashes into the flashes ref.
97
+ * The flasher argument ultimately determines what flashes ref they should be added to.
98
+ * @param flasher FlashAPI
99
+ */
100
+ export declare const loadWindowFlashes: (flasher: FlasherAPI) => void;
@@ -1,2 +1,14 @@
1
- declare const _default: import("vue").DefineComponent<{}, () => void, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, import("vue").EmitsOptions, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<{} & {} & {}>, {}>;
1
+ declare const _default: import("vue").DefineComponent<{
2
+ tag: {
3
+ type: import("vue").PropType<string>;
4
+ } & {
5
+ default: string;
6
+ };
7
+ }, () => void, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, Record<string, any>, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<{
8
+ tag?: unknown;
9
+ } & {
10
+ tag: string;
11
+ } & {}>, {
12
+ tag: string;
13
+ }>;
2
14
  export default _default;
@@ -0,0 +1,57 @@
1
+ declare type ModelValue = string | number;
2
+ declare type RadioCard = {
3
+ disabled?: boolean;
4
+ help?: string;
5
+ label: string;
6
+ sublabel?: string;
7
+ value: ModelValue;
8
+ };
9
+ declare const _default: import("vue").DefineComponent<{
10
+ columns: {
11
+ type: import("vue").PropType<2 | 3>;
12
+ } & {
13
+ default: undefined;
14
+ };
15
+ help: {
16
+ type: import("vue").PropType<string>;
17
+ } & {
18
+ default: string;
19
+ };
20
+ legend: {
21
+ type: import("vue").PropType<string>;
22
+ } & {
23
+ default: string;
24
+ };
25
+ modelValue: {
26
+ type: import("vue").PropType<ModelValue>;
27
+ } & {
28
+ default: undefined;
29
+ };
30
+ options: {
31
+ type: import("vue").PropType<RadioCard[]>;
32
+ required: true;
33
+ };
34
+ }, () => void, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
35
+ "update:modelValue": (modelValue: ModelValue) => void;
36
+ }, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<{
37
+ columns?: unknown;
38
+ help?: unknown;
39
+ legend?: unknown;
40
+ modelValue?: unknown;
41
+ options?: unknown;
42
+ } & {
43
+ help: string;
44
+ options: RadioCard[];
45
+ legend: string;
46
+ } & {
47
+ modelValue?: ModelValue | undefined;
48
+ columns?: 2 | 3 | undefined;
49
+ }> & {
50
+ "onUpdate:modelValue"?: ((modelValue: ModelValue) => any) | undefined;
51
+ }, {
52
+ modelValue: ModelValue;
53
+ help: string;
54
+ legend: string;
55
+ columns: 2 | 3;
56
+ }>;
57
+ export default _default;
@@ -28,11 +28,12 @@ import { default as InputLabel } from "./forms/InputLabel.vue";
28
28
  import { default as FieldsetLegend } from "./forms/FieldsetLegend.vue";
29
29
  import { default as MultiCheckboxes } from "./forms/MultiCheckboxes.vue";
30
30
  import { default as Radio } from "./forms/Radio.vue";
31
+ import { default as RadioCards } from "./forms/RadioCards.vue";
31
32
  import { default as Select } from "./forms/Select.vue";
32
33
  import { default as TextArea } from "./forms/TextArea.vue";
33
34
  import { default as YesOrNoRadio } from "./forms/YesOrNoRadio.vue";
34
35
  export { ActionsDropdown, Cards, ContentModal, DateFilter, DetailList, DownloadCell, Flash, Modal, SidebarLayout, Slideover, StackedLayout, Popover, PopoverContent, PopoverPosition, // Type export
35
- Paginator, Spinner, StaticTable, Steps, Table, Tabs, Toggle, Tooltip, BaseInput, Checkbox, DateRangePicker, InputHelp, InputLabel, FieldsetLegend, MultiCheckboxes, Radio, Select, TextArea, YesOrNoRadio, };
36
+ Paginator, Spinner, StaticTable, Steps, Table, Tabs, Toggle, Tooltip, BaseInput, Checkbox, DateRangePicker, InputHelp, InputLabel, FieldsetLegend, MultiCheckboxes, Radio, RadioCards, Select, TextArea, YesOrNoRadio, };
36
37
  /**
37
38
  * declare global component types for App.use(Trees)
38
39
  */
@@ -66,6 +67,7 @@ export interface TreesComponents {
66
67
  FieldsetLegend: typeof FieldsetLegend;
67
68
  MultiCheckboxes: typeof MultiCheckboxes;
68
69
  Radio: typeof Radio;
70
+ RadioCards: typeof RadioCards;
69
71
  Select: typeof Select;
70
72
  TextArea: typeof TextArea;
71
73
  YesOrNoRadio: typeof YesOrNoRadio;
@@ -0,0 +1,12 @@
1
+ export interface Pagination {
2
+ page: number;
3
+ perPage: number;
4
+ totalItems: number;
5
+ totalPages: number;
6
+ }
7
+ export interface PaginationItems<T = any> {
8
+ items: T[];
9
+ }
10
+ export interface PaginationData<T = any> {
11
+ data: Pagination & PaginationItems<T>;
12
+ }