@xy-planning-network/trees 0.4.8-rc-2 → 0.4.9-rc-2

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-rc-2",
3
+ "version": "0.4.9-rc-2",
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,181 @@
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 FieldsetLegend from "./FieldsetLegend.vue"
12
+
13
+ /*
14
+ * NOTE (spk) headless UI introduced a "name" prop that includes a hidden field
15
+ * to use the modelValue inside of forms. It does not however resolve the issue of
16
+ * supporting HTML5 form validation, so we'll add our own hidden radio buttons to support both.
17
+ *
18
+ * The headless technique does include supporting complex modelValues such as objects, which we may
19
+ * need in the future. We can revist required validation at that time using a singular hidden checkbox.
20
+ */
21
+
22
+ type ModelValue = string | number
23
+
24
+ type RadioCard = {
25
+ disabled?: boolean
26
+ help?: string
27
+ label: string
28
+ sublabel?: string
29
+ value: ModelValue
30
+ }
31
+
32
+ const props = withDefaults(
33
+ defineProps<{
34
+ columns?: 2 | 3
35
+ help?: string
36
+ legend?: string
37
+ modelValue?: ModelValue
38
+ options: RadioCard[]
39
+ }>(),
40
+ {
41
+ columns: undefined,
42
+ help: "",
43
+ legend: "",
44
+ modelValue: undefined,
45
+ }
46
+ )
47
+
48
+ const emit = defineEmits<{
49
+ (e: "update:modelValue", modelValue: ModelValue): void
50
+ }>()
51
+
52
+ const attrs = useAttrs()
53
+ const uuid = (attrs.id as string) || Uniques.CreateIdAttribute()
54
+
55
+ // tracking internal state separate from modelValue
56
+ // allows v-model to be undefined by the consumer but still supports
57
+ // the display requirements of the component.
58
+ // this is usful when the component is used inside a form element and
59
+ // tracking v-model isn't required.
60
+ const internalState = ref()
61
+ const invalid = ref<boolean>()
62
+ const checked = computed(() => {
63
+ if (props.modelValue === undefined) {
64
+ return internalState.value
65
+ }
66
+
67
+ return props.modelValue
68
+ })
69
+
70
+ const onChange = (val: ModelValue) => {
71
+ internalState.value = val
72
+ invalid.value = false
73
+ emit("update:modelValue", val)
74
+ }
75
+
76
+ const nameAttr = computed(() => {
77
+ return typeof attrs.name === "string" && attrs.name !== "" ? attrs.name : uuid
78
+ })
79
+ </script>
80
+
81
+ <template>
82
+ <RadioGroup
83
+ :modelValue="checked"
84
+ @update:model-value="onChange"
85
+ :disabled="typeof attrs.disabled === 'boolean' ? attrs.disabled : false"
86
+ :aria-invalid="invalid === true ? 'true' : null"
87
+ :aria-errormessage="invalid === true ? `error-${uuid}` : null"
88
+ >
89
+ <RadioGroupLabel v-if="legend" class="block">
90
+ <FieldsetLegend tag="div">{{ legend }}</FieldsetLegend>
91
+ </RadioGroupLabel>
92
+ <RadioGroupDescription v-if="help">
93
+ <InputHelp :text="help" />
94
+ </RadioGroupDescription>
95
+ <div v-if="invalid === true" :id="`error-${uuid}`" class="sr-only">
96
+ Please select one of these options.
97
+ </div>
98
+
99
+ <div
100
+ class="mt-4 grid grid-cols-1 gap-y-5 gap-x-4 relative"
101
+ :class="{
102
+ 'sm:grid-cols-2': columns === 2,
103
+ 'sm:grid-cols-3': columns === 3,
104
+ }"
105
+ >
106
+ <RadioGroupOption
107
+ as="template"
108
+ v-for="option in options"
109
+ :disabled="option?.disabled ? option.disabled : false"
110
+ :key="option.value"
111
+ :value="option.value"
112
+ v-slot="{ active, checked, disabled }"
113
+ >
114
+ <div
115
+ :class="[
116
+ checked ? 'border-transparent' : 'border-gray-300',
117
+ active ? 'border-blue-500 ring-2 ring-blue-500' : '',
118
+ 'relative bg-white border rounded-lg shadow-sm p-4 flex cursor-pointer focus:outline-none',
119
+ disabled ? 'opacity-75' : '',
120
+ ]"
121
+ >
122
+ <div class="flex-1 flex pr-1">
123
+ <div class="flex flex-col">
124
+ <RadioGroupLabel as="div">
125
+ <InputLabel
126
+ tag="div"
127
+ class="mt-auto mb-auto"
128
+ :label="option.label"
129
+ />
130
+ </RadioGroupLabel>
131
+ <RadioGroupDescription v-if="option.help" as="div">
132
+ <InputHelp tag="div" class="mt-auto" :text="option.help" />
133
+ </RadioGroupDescription>
134
+ <div
135
+ v-if="option.sublabel || $slots.sublabel"
136
+ class="mt-auto mb-0"
137
+ >
138
+ <RadioGroupDescription
139
+ as="div"
140
+ class="font-semibold leading-snug mt-4 text-gray-900 text-sm"
141
+ >
142
+ {{ option.sublabel }}
143
+ <slot
144
+ name="sublabel"
145
+ :active="active"
146
+ :checked="checked"
147
+ :disabled="disabled"
148
+ :option="option"
149
+ />
150
+ </RadioGroupDescription>
151
+ </div>
152
+ </div>
153
+ </div>
154
+ <CheckCircleIcon
155
+ :class="[!checked ? 'invisible' : '', 'h-5 w-5 text-blue-600']"
156
+ aria-hidden="true"
157
+ />
158
+ <div
159
+ :class="[
160
+ active ? 'border' : 'border-2',
161
+ checked ? 'border-blue-500' : 'border-transparent',
162
+ 'absolute -inset-px rounded-lg pointer-events-none',
163
+ ]"
164
+ aria-hidden="true"
165
+ />
166
+ <input
167
+ class="sr-only top-1 left-1"
168
+ aria-hidden="true"
169
+ :checked="checked"
170
+ :name="nameAttr"
171
+ :required="attrs.required !== undefined && attrs.required !== false"
172
+ tabindex="-1"
173
+ type="radio"
174
+ :value="option.value"
175
+ @invalid="invalid = true"
176
+ />
177
+ </div>
178
+ </RadioGroupOption>
179
+ </div>
180
+ </RadioGroup>
181
+ </template>
@@ -1,18 +1,24 @@
1
- import { AxiosResponse, AxiosRequestConfig } from "axios";
1
+ import { AxiosRequestConfig } from "axios";
2
2
  export declare type RequestMethod = "GET" | "get" | "PUT" | "put" | "POST" | "post" | "DELETE" | "delete";
3
- export interface TreesResponse<T> extends AxiosResponse<T> {
4
- data: T;
5
- }
6
3
  export interface RequestOptions {
4
+ /**
5
+ * returns the nested data key inside the AxiosResponse data when true
6
+ */
7
7
  dataIntercept?: boolean;
8
+ /**
9
+ * disables the full screen loading interface during the request when true
10
+ */
8
11
  skipLoader?: boolean;
12
+ /**
13
+ * artificially delay's the request by the time specified when set
14
+ */
9
15
  withDelay?: number;
10
16
  }
11
17
  declare const BaseAPI: {
12
18
  makeRequest<T = any>(config: AxiosRequestConfig, opts: RequestOptions): Promise<T>;
13
19
  get<T_1 = any>(path: string, opts: RequestOptions, params?: Record<string, unknown> | undefined): Promise<T_1>;
14
20
  delete<T_2 = any>(path: string, opts: RequestOptions): Promise<T_2>;
15
- post<T_3 = any>(path: string, data: Record<string, unknown>, opts: RequestOptions): Promise<T_3>;
16
- 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>;
17
23
  };
18
24
  export default BaseAPI;
@@ -1,4 +1,4 @@
1
- import { AxiosError, AxiosRequestConfig } from "axios";
1
+ import { AxiosError } from "axios";
2
2
  import { Ref, ShallowRef } from "vue";
3
3
  import type { RequestMethod, RequestOptions } from "../api/base";
4
4
  /**
@@ -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, config?: AxiosRequestConfig) => 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
@@ -61,7 +61,7 @@ export interface UseBaseAPI<T> {
61
61
  * @param initConfig {AxiosRequestConfig}
62
62
  * @returns {UseBaseAPI<T>}
63
63
  */
64
- export default function useBaseAPI<T = any>(path: string, method?: RequestMethod, initOpts?: UseBaseAPIOptions, initConfig?: AxiosRequestConfig): {
64
+ export default function useBaseAPI<T = any>(path: string, method?: RequestMethod, initOpts?: UseBaseAPIOptions): {
65
65
  result: Ref<T | undefined>;
66
66
  error: ShallowRef<Error | AxiosError<T, any> | undefined>;
67
67
  isFinished: Ref<boolean>;
@@ -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>, execOpts?: RequestOptions, execConfig?: AxiosRequestConfig) => 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
@@ -78,7 +78,7 @@ export default function useBaseAPI<T = any>(path: string, method?: RequestMethod
78
78
  * @param initConfig {AxiosRequestConfig}
79
79
  * @returns {UseBaseAPI<T>}
80
80
  */
81
- export declare function useBaseAPIGet<T = any>(url: string, initOpts?: UseBaseAPIOptions, initConfig?: AxiosRequestConfig): UseBaseAPI<T>;
81
+ export declare function useBaseAPIGet<T = any>(url: string, opts?: UseBaseAPIOptions): UseBaseAPI<T>;
82
82
  /**
83
83
  * useBaseAPIDelete is a convenience function for useBaseAPI
84
84
  * @param path {string} the api path or full url for the
@@ -86,7 +86,7 @@ export declare function useBaseAPIGet<T = any>(url: string, initOpts?: UseBaseAP
86
86
  * @param initConfig {AxiosRequestConfig}
87
87
  * @returns {UseBaseAPI<T>}
88
88
  */
89
- export declare function useBaseAPIDelete<T = any>(url: string, initOpts?: UseBaseAPIOptions, initConfig?: AxiosRequestConfig): UseBaseAPI<T>;
89
+ export declare function useBaseAPIDelete<T = any>(url: string, opts?: UseBaseAPIOptions): UseBaseAPI<T>;
90
90
  /**
91
91
  * useBaseAPIPost is a convenience function for useBaseAPI
92
92
  * @param path {string} the api path or full url for the
@@ -94,7 +94,7 @@ export declare function useBaseAPIDelete<T = any>(url: string, initOpts?: UseBas
94
94
  * @param initConfig {AxiosRequestConfig}
95
95
  * @returns {UseBaseAPI<T>}
96
96
  */
97
- export declare function useBaseAPIPost<T = any>(url: string, initOpts?: UseBaseAPIOptions, initConfig?: AxiosRequestConfig): UseBaseAPI<T>;
97
+ export declare function useBaseAPIPost<T = any>(url: string, opts?: UseBaseAPIOptions): UseBaseAPI<T>;
98
98
  /**
99
99
  * useBaseAPIPut is a convenience function for useBaseAPI
100
100
  * @param path {string} the api path or full url for the
@@ -102,4 +102,4 @@ export declare function useBaseAPIPost<T = any>(url: string, initOpts?: UseBaseA
102
102
  * @param initConfig {AxiosRequestConfig}
103
103
  * @returns {UseBaseAPI<T>}
104
104
  */
105
- export declare function useBaseAPIPut<T = any>(url: string, initOpts?: UseBaseAPIOptions, initConfig?: AxiosRequestConfig): UseBaseAPI<T>;
105
+ export declare function useBaseAPIPut<T = any>(url: string, opts?: UseBaseAPIOptions): UseBaseAPI<T>;
@@ -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;
package/types/entry.d.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  import { Plugin } from "vue";
2
2
  import BaseAPI from "./api/base";
3
+ import type { RequestOptions } from "./api/base";
3
4
  declare const install: Exclude<Plugin["install"], undefined>;
4
5
  export default install;
5
6
  export * from "./composables/index";
6
7
  export * from "./lib-components/index";
7
8
  export { BaseAPI };
9
+ export type { RequestOptions };
@@ -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;