@signal24/vue-foundation 4.30.7 → 4.30.8

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.
@@ -149,11 +149,11 @@ function ft(e) {
149
149
  }
150
150
  function pn(e) {
151
151
  const t = P.findIndex((o) => o.vnode.component === e.component);
152
- return t >= 0 ? (P[t].props.callback(), !0) : !1;
152
+ return t >= 0 ? (P[t].props.callback?.(), !0) : !1;
153
153
  }
154
154
  function vn(e) {
155
155
  const t = P.findIndex((o) => o.id === e);
156
- return t >= 0 ? (P[t].props.callback(), !0) : !1;
156
+ return t >= 0 ? (P[t].props.callback?.(), !0) : !1;
157
157
  }
158
158
  function ie(e) {
159
159
  const t = P.indexOf(e);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@signal24/vue-foundation",
3
3
  "type": "module",
4
- "version": "4.30.7",
4
+ "version": "4.30.8",
5
5
  "description": "Common components, directives, and helpers for Vue 3 apps",
6
6
  "module": "./dist/vue-foundation.es.js",
7
7
  "exports": {
@@ -1,14 +1,12 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import type { Writable } from 'type-fest';
3
2
  import {
4
3
  type AllowedComponentProps,
4
+ type Component,
5
+ type ComponentCustomProps,
5
6
  type ComponentInternalInstance,
6
- type ComponentPublicInstance,
7
- type ComputedOptions,
8
7
  defineComponent,
9
8
  h,
10
9
  markRaw,
11
- type MethodOptions,
12
10
  type Raw,
13
11
  reactive,
14
12
  renderList,
@@ -23,23 +21,23 @@ import { VfOptions } from '@/config';
23
21
  import OverlayAnchor from './overlay-anchor.vue';
24
22
  import type { OverlayAnchorOptions } from './overlay-types';
25
23
 
26
- interface OverlayOptions<C extends OverlayComponent, R extends ComponentReturn<C>> {
24
+ interface OverlayOptions<C extends Component, R extends ComponentReturn<C>> {
27
25
  anchor?: OverlayAnchorOptions;
28
26
  onCallback?: (result: R) => void | Promise<boolean>;
29
27
  }
30
28
 
31
- export interface OverlayInjection<C extends OverlayComponent, R extends ComponentReturn<C>> {
29
+ export interface OverlayInjection<C extends Component> {
32
30
  id: string;
33
- component: OverlayComponentUnwrapped<C>;
34
- props: OverlayComponentProps<C>;
35
- options: OverlayOptions<C, R>;
31
+ component: Raw<C>;
32
+ props: { callback?: () => void } & OverlayComponentProps<C>;
33
+ options: OverlayOptions<C, any>;
36
34
  vnode: VNode;
37
35
  wrapperVnode?: VNode;
38
36
  }
39
37
 
40
38
  let overlayCount = 0;
41
39
 
42
- const OverlayInjections: OverlayInjection<any, any>[] = reactive([]);
40
+ const OverlayInjections: OverlayInjection<any>[] = reactive([]);
43
41
  watch(OverlayInjections, () => {
44
42
  VfOptions.onOverlaysChanged?.(OverlayInjections.length);
45
43
  });
@@ -55,57 +53,47 @@ export const OverlayContainer = defineComponent({
55
53
  }
56
54
  });
57
55
 
58
- // copied in from Vue since it's not exported
59
- // tood: it may be a lot easier than this. see the docs for props passed to "h"
60
- export type Vue__ComponentPublicInstanceConstructor<
61
- T extends ComponentPublicInstance<Props, RawBindings, D, C, M> = ComponentPublicInstance<any>,
62
- Props = any,
63
- RawBindings = any,
64
- D = any,
65
- C extends ComputedOptions = ComputedOptions,
66
- M extends MethodOptions = MethodOptions
67
- > = {
68
- __isFragment?: never;
69
- __isTeleport?: never;
70
- __isSuspense?: never;
71
- new (...args: any[]): T;
56
+ export type AnyComponentPublicInstance = { $?: ComponentInternalInstance };
57
+
58
+ // Handle both regular and generic components
59
+ type ExtractComponentProps<C> = C extends new (...args: any) => any
60
+ ? InstanceType<C>['$props']
61
+ : C extends (props: infer P, ...args: any) => any
62
+ ? P
63
+ : C extends { __props?: infer P }
64
+ ? P
65
+ : never;
66
+
67
+ // Remove Vue's internal prop types and the Record<string, unknown> index signature
68
+ type CleanProps<P> = {
69
+ [K in keyof P as K extends keyof (VNodeProps & AllowedComponentProps & ComponentCustomProps) ? never : string extends K ? never : K]: P[K];
72
70
  };
73
71
 
74
- export type ObjectComponentConfig<T extends Vue__ComponentPublicInstanceConstructor> =
75
- T extends Vue__ComponentPublicInstanceConstructor<infer P> ? P : never;
76
- export type ObjectComponentProps<T extends Vue__ComponentPublicInstanceConstructor> = Writable<
77
- Omit<ObjectComponentConfig<T>['$props'], keyof VNodeProps | keyof AllowedComponentProps>
78
- >;
79
-
80
- // eslint-disable-next-line @typescript-eslint/no-empty-object-type
81
- type ObjectOrDefault<T> = T extends object ? T : PropsWithCallback<{}>;
82
- export type OverlayComponent = Vue__ComponentPublicInstanceConstructor | ((props: any) => any);
83
- export type OverlayComponentConfig<T> = T extends Vue__ComponentPublicInstanceConstructor
84
- ? {
85
- props: ObjectComponentProps<T>;
86
- component: Raw<T>;
87
- }
88
- : T extends (props: infer P) => any
89
- ? {
90
- props: Omit<ObjectOrDefault<P>, keyof VNodeProps | keyof AllowedComponentProps>;
91
- component: T;
92
- }
93
- : never;
94
- export type OverlayComponentUnwrapped<T extends OverlayComponent> = OverlayComponentConfig<T>['component'];
95
- export type OverlayComponentProps<T extends OverlayComponent> = OverlayComponentConfig<T>['props'];
96
-
97
- interface PropsWithCallback<T> {
98
- callback?: (result: T) => void;
99
- }
100
- type ComponentReturn<M extends OverlayComponent> = OverlayComponentProps<M> extends PropsWithCallback<infer R> ? R : never;
72
+ // Check if component has a callback prop with correct signature
73
+ type HasCallbackProp<C> =
74
+ CleanProps<ExtractComponentProps<C>> extends {
75
+ callback: (result: any) => void;
76
+ }
77
+ ? true
78
+ : false;
101
79
 
102
- export type AnyComponentPublicInstance = { $?: ComponentInternalInstance };
80
+ // Constraint type - resolves to C if valid, never if not
81
+ type OverlayComponent<C extends Component> = HasCallbackProp<C> extends true ? C : never;
82
+
83
+ type ComponentReturn<C> =
84
+ CleanProps<ExtractComponentProps<C>> extends {
85
+ callback: (result: infer R) => void;
86
+ }
87
+ ? R
88
+ : never;
89
+
90
+ type OverlayComponentProps<C> = CleanProps<ExtractComponentProps<C>>;
103
91
 
104
- export function createOverlayInjection<C extends OverlayComponent, R extends ComponentReturn<C>>(
105
- component: C,
92
+ export function createOverlayInjection<C extends Component, R extends ComponentReturn<C>>(
93
+ component: OverlayComponent<C>,
106
94
  props: OverlayComponentProps<C>,
107
95
  options?: OverlayOptions<C, R>
108
- ): OverlayInjection<C, R> {
96
+ ): OverlayInjection<C> {
109
97
  // create or reconfigure the existing overlay target
110
98
  // re-injecting every time keeps the overlay container at the very end of the DOM
111
99
  const targetEl = document.getElementById('vf-overlay-target') ?? document.createElement('div');
@@ -119,9 +107,9 @@ export function createOverlayInjection<C extends OverlayComponent, R extends Com
119
107
  const wrapperVnode = options?.anchor ? h(OverlayAnchor, { overlayId, anchor: options.anchor }, () => [vnode]) : undefined;
120
108
 
121
109
  // todo: dunno what's going on with types here
122
- const injection: OverlayInjection<C, R> = {
110
+ const injection: OverlayInjection<C> = {
123
111
  id: overlayId,
124
- component: rawComponent as any,
112
+ component: rawComponent,
125
113
  props,
126
114
  options: options ?? {},
127
115
  vnode,
@@ -148,7 +136,7 @@ export function dismissOverlayInjectionByInternalInstance(instance: ComponentInt
148
136
  export function dismissOverlayInjectionByVnode(vnode: VNode) {
149
137
  const injectionIdx = OverlayInjections.findIndex(i => i.vnode.component === vnode.component);
150
138
  if (injectionIdx >= 0) {
151
- OverlayInjections[injectionIdx]!.props.callback();
139
+ OverlayInjections[injectionIdx]!.props.callback?.();
152
140
  return true;
153
141
  }
154
142
  return false;
@@ -157,26 +145,26 @@ export function dismissOverlayInjectionByVnode(vnode: VNode) {
157
145
  export function dismissOverlayInjectionById(id: string) {
158
146
  const injectionIdx = OverlayInjections.findIndex(i => i.id === id);
159
147
  if (injectionIdx >= 0) {
160
- OverlayInjections[injectionIdx]!.props.callback();
148
+ OverlayInjections[injectionIdx]!.props.callback?.();
161
149
  return true;
162
150
  }
163
151
  return false;
164
152
  }
165
153
 
166
- export function removeOverlayInjection(injection: OverlayInjection<any, any>) {
154
+ export function removeOverlayInjection(injection: OverlayInjection<any>) {
167
155
  const index = OverlayInjections.indexOf(injection);
168
156
  if (index >= 0) {
169
157
  OverlayInjections.splice(index, 1);
170
158
  }
171
159
  }
172
160
 
173
- export async function presentOverlay<C extends OverlayComponent, R extends ComponentReturn<C>>(
174
- component: C,
161
+ export async function presentOverlay<C extends Component, R extends ComponentReturn<C>>(
162
+ component: OverlayComponent<C>,
175
163
  props: Omit<OverlayComponentProps<C>, 'callback'>,
176
164
  options?: OverlayOptions<C, R>
177
165
  ): Promise<R | undefined> {
178
166
  return new Promise<R>(resolve => {
179
- let overlayInjection: OverlayInjection<C, R> | null = null;
167
+ let overlayInjection: OverlayInjection<C> | null = null;
180
168
  const callback = async (result: R) => {
181
169
  if (options?.onCallback) {
182
170
  const hookResult = options.onCallback(result);
@@ -197,12 +185,12 @@ export async function presentOverlay<C extends OverlayComponent, R extends Compo
197
185
  });
198
186
  }
199
187
 
200
- export async function updateOverlayProps<C extends OverlayComponent>(
201
- injection: OverlayInjection<C, any>,
188
+ export async function updateOverlayProps<C extends Component>(
189
+ injection: OverlayInjection<C>,
202
190
  props: Partial<Omit<OverlayComponentProps<C>, 'callback'>>
203
191
  ) {
204
192
  const targetProps = injection.vnode.component!.props;
205
193
  for (const key in props) {
206
- targetProps[key] = props[key];
194
+ targetProps[key] = (props as any)[key];
207
195
  }
208
196
  }
@@ -2,7 +2,7 @@ import { createOverlayInjection, type OverlayInjection, removeOverlayInjection }
2
2
  import Toast, { type IToastOptions } from './vf-toast.vue';
3
3
 
4
4
  export function showToast(options: IToastOptions) {
5
- const injection: OverlayInjection<typeof Toast, unknown> = createOverlayInjection(Toast, {
5
+ const injection: OverlayInjection<typeof Toast> = createOverlayInjection(Toast, {
6
6
  ...options,
7
7
  callback: () => removeOverlayInjection(injection)
8
8
  });