@aerogel/core 0.1.1 → 0.1.2-next.0532ffc3845be5e86d770e8e823f5216ef34dfbf
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/dist/aerogel-core.d.ts +539 -317
- package/dist/aerogel-core.js +1938 -1546
- package/dist/aerogel-core.js.map +1 -1
- package/package.json +4 -2
- package/src/bootstrap/index.ts +2 -1
- package/src/components/AppLayout.vue +1 -1
- package/src/components/AppOverlays.vue +3 -2
- package/src/components/contracts/AlertModal.ts +1 -1
- package/src/components/contracts/Button.ts +1 -1
- package/src/components/contracts/Combobox.ts +5 -0
- package/src/components/contracts/ConfirmModal.ts +5 -2
- package/src/components/contracts/Modal.ts +8 -3
- package/src/components/contracts/PromptModal.ts +6 -2
- package/src/components/contracts/Select.ts +98 -4
- package/src/components/contracts/Toast.ts +1 -1
- package/src/components/contracts/index.ts +1 -0
- package/src/components/headless/HeadlessInputInput.vue +27 -5
- package/src/components/headless/HeadlessModal.vue +6 -34
- package/src/components/headless/HeadlessModalContent.vue +5 -12
- package/src/components/headless/HeadlessSelect.vue +10 -91
- package/src/components/headless/HeadlessSelectOption.vue +1 -5
- package/src/components/index.ts +1 -1
- package/src/components/ui/AdvancedOptions.vue +4 -13
- package/src/components/ui/Button.vue +1 -0
- package/src/components/ui/Combobox.vue +94 -0
- package/src/components/ui/ComboboxLabel.vue +29 -0
- package/src/components/ui/ComboboxOption.vue +46 -0
- package/src/components/ui/ComboboxOptions.vue +71 -0
- package/src/components/ui/ComboboxTrigger.vue +67 -0
- package/src/components/ui/ConfirmModal.vue +7 -2
- package/src/components/ui/Details.vue +33 -0
- package/src/components/ui/Form.vue +1 -1
- package/src/components/ui/Input.vue +12 -4
- package/src/components/ui/LoadingModal.vue +1 -2
- package/src/components/ui/Modal.vue +53 -33
- package/src/components/ui/ProgressBar.vue +16 -2
- package/src/components/ui/PromptModal.vue +7 -2
- package/src/components/ui/Select.vue +2 -0
- package/src/components/ui/SelectTrigger.vue +13 -2
- package/src/components/ui/SettingsModal.vue +1 -1
- package/src/components/ui/Toast.vue +1 -0
- package/src/components/ui/index.ts +6 -1
- package/src/components/vue/Provide.vue +11 -0
- package/src/components/vue/index.ts +1 -0
- package/src/directives/index.ts +7 -7
- package/src/errors/Errors.ts +4 -0
- package/src/errors/index.ts +5 -0
- package/src/forms/FormController.test.ts +4 -4
- package/src/forms/FormController.ts +23 -13
- package/src/forms/index.ts +11 -0
- package/src/forms/utils.ts +36 -17
- package/src/forms/validation.ts +5 -1
- package/src/index.css +10 -0
- package/src/jobs/Job.ts +1 -1
- package/src/plugins/index.ts +1 -3
- package/src/services/App.state.ts +1 -0
- package/src/services/App.ts +4 -0
- package/src/services/index.ts +7 -0
- package/src/testing/index.ts +1 -2
- package/src/ui/UI.state.ts +0 -11
- package/src/ui/UI.ts +43 -125
- package/src/ui/index.ts +1 -0
- package/src/ui/modals.ts +36 -0
- package/src/utils/classes.ts +2 -3
- package/src/utils/composition/reactiveSet.test.ts +32 -0
- package/src/utils/composition/reactiveSet.ts +61 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/time.ts +7 -0
- package/src/components/AppModals.vue +0 -14
- package/src/components/ui/ModalContext.vue +0 -31
package/src/ui/UI.ts
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
|
-
import { after, facade, fail, isDevelopment,
|
|
2
|
-
import { markRaw,
|
|
3
|
-
import type {
|
|
4
|
-
import type { Component } from 'vue';
|
|
5
|
-
import type { ClosureArgs } from '@noeldemartin/utils';
|
|
1
|
+
import { after, facade, fail, isDevelopment, uuid } from '@noeldemartin/utils';
|
|
2
|
+
import { markRaw, unref } from 'vue';
|
|
3
|
+
import type { Constructor } from '@noeldemartin/utils';
|
|
4
|
+
import type { Component, ComputedOptions, MethodOptions } from 'vue';
|
|
6
5
|
|
|
7
|
-
import App from '@aerogel/core/services/App';
|
|
8
6
|
import Events from '@aerogel/core/services/Events';
|
|
7
|
+
import { closeModal, createModal, modals, showModal } from '@aerogel/core/ui/modals';
|
|
8
|
+
import type { GetModalProps, GetModalResponse } from '@aerogel/core/ui/modals';
|
|
9
|
+
import type { AcceptRefs } from '@aerogel/core/utils';
|
|
10
|
+
import type { AlertModalExpose, AlertModalProps } from '@aerogel/core/components/contracts/AlertModal';
|
|
11
|
+
import type { ButtonVariant } from '@aerogel/core/components/contracts/Button';
|
|
12
|
+
import type { LoadingModalExpose, LoadingModalProps } from '@aerogel/core/components/contracts/LoadingModal';
|
|
13
|
+
import type { ToastAction, ToastExpose, ToastProps, ToastVariant } from '@aerogel/core/components/contracts/Toast';
|
|
9
14
|
import type {
|
|
10
15
|
ConfirmModalCheckboxes,
|
|
16
|
+
ConfirmModalEmits,
|
|
11
17
|
ConfirmModalExpose,
|
|
12
18
|
ConfirmModalProps,
|
|
13
19
|
} from '@aerogel/core/components/contracts/ConfirmModal';
|
|
@@ -15,42 +21,30 @@ import type {
|
|
|
15
21
|
ErrorReportModalExpose,
|
|
16
22
|
ErrorReportModalProps,
|
|
17
23
|
} from '@aerogel/core/components/contracts/ErrorReportModal';
|
|
18
|
-
import type {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
import type { ToastAction, ToastExpose, ToastProps, ToastVariant } from '@aerogel/core/components/contracts/Toast';
|
|
24
|
+
import type {
|
|
25
|
+
PromptModalEmits,
|
|
26
|
+
PromptModalExpose,
|
|
27
|
+
PromptModalProps,
|
|
28
|
+
} from '@aerogel/core/components/contracts/PromptModal';
|
|
24
29
|
|
|
25
30
|
import Service from './UI.state';
|
|
26
31
|
import { MOBILE_BREAKPOINT, getCurrentLayout } from './utils';
|
|
27
|
-
import type {
|
|
32
|
+
import type { UIToast } from './UI.state';
|
|
28
33
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
hasClosed(result: T | undefined): void;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export type ModalResult<T> = ModalExposeResult<ComponentExposed<T>>;
|
|
35
|
-
export type ModalExposeResult<T> = T extends { close(result?: infer Result): Promise<void> } ? Result : unknown;
|
|
36
|
-
export type UIComponent<Props = {}, Exposed = {}> = { new (...args: ClosureArgs): Exposed & { $props: Props } };
|
|
34
|
+
export type UIComponent<Props = {}, Exposed = {}, Emits = {}> = Constructor<{ $emit?: Emits } & Exposed> &
|
|
35
|
+
Component<Props, {}, {}, ComputedOptions, MethodOptions, {}, {}>;
|
|
37
36
|
|
|
38
37
|
export interface UIComponents {
|
|
39
38
|
'alert-modal': UIComponent<AlertModalProps, AlertModalExpose>;
|
|
40
|
-
'confirm-modal': UIComponent<ConfirmModalProps, ConfirmModalExpose>;
|
|
39
|
+
'confirm-modal': UIComponent<ConfirmModalProps, ConfirmModalExpose, ConfirmModalEmits>;
|
|
41
40
|
'error-report-modal': UIComponent<ErrorReportModalProps, ErrorReportModalExpose>;
|
|
42
41
|
'loading-modal': UIComponent<LoadingModalProps, LoadingModalExpose>;
|
|
43
|
-
'prompt-modal': UIComponent<PromptModalProps, PromptModalExpose>;
|
|
42
|
+
'prompt-modal': UIComponent<PromptModalProps, PromptModalExpose, PromptModalEmits>;
|
|
44
43
|
'router-link': UIComponent;
|
|
45
44
|
'startup-crash': UIComponent;
|
|
46
45
|
toast: UIComponent<ToastProps, ToastExpose>;
|
|
47
46
|
}
|
|
48
47
|
|
|
49
|
-
export interface UIModalContext {
|
|
50
|
-
modal: UIModal;
|
|
51
|
-
childIndex?: number;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
48
|
export type ConfirmOptions = AcceptRefs<{
|
|
55
49
|
acceptText?: string;
|
|
56
50
|
acceptVariant?: ButtonVariant;
|
|
@@ -91,7 +85,6 @@ export interface ToastOptions {
|
|
|
91
85
|
|
|
92
86
|
export class UIService extends Service {
|
|
93
87
|
|
|
94
|
-
private modalCallbacks: Record<string, Partial<ModalCallbacks>> = {};
|
|
95
88
|
private components: Partial<UIComponents> = {};
|
|
96
89
|
|
|
97
90
|
public registerComponent<T extends keyof UIComponents>(name: T, component: UIComponents[T]): void {
|
|
@@ -153,11 +146,11 @@ export class UIService extends Service {
|
|
|
153
146
|
};
|
|
154
147
|
|
|
155
148
|
const properties = getProperties();
|
|
156
|
-
const
|
|
157
|
-
const confirmed = typeof
|
|
149
|
+
const { response } = await this.modal(this.requireComponent('confirm-modal'), properties);
|
|
150
|
+
const confirmed = typeof response === 'object' ? response[0] : (response ?? false);
|
|
158
151
|
const checkboxes =
|
|
159
|
-
typeof
|
|
160
|
-
?
|
|
152
|
+
typeof response === 'object'
|
|
153
|
+
? response[1]
|
|
161
154
|
: Object.entries(properties.checkboxes ?? {}).reduce(
|
|
162
155
|
(values, [checkbox, { default: defaultValue }]) => ({
|
|
163
156
|
[checkbox]: defaultValue ?? false,
|
|
@@ -205,8 +198,8 @@ export class UIService extends Service {
|
|
|
205
198
|
} as PromptModalProps;
|
|
206
199
|
};
|
|
207
200
|
|
|
208
|
-
const
|
|
209
|
-
const result = trim && typeof
|
|
201
|
+
const { response } = await this.modal(this.requireComponent('prompt-modal'), getProperties());
|
|
202
|
+
const result = trim && typeof response === 'string' ? response?.trim() : response;
|
|
210
203
|
|
|
211
204
|
return result ?? null;
|
|
212
205
|
}
|
|
@@ -253,7 +246,9 @@ export class UIService extends Service {
|
|
|
253
246
|
return operationPromise;
|
|
254
247
|
}
|
|
255
248
|
|
|
256
|
-
const modal =
|
|
249
|
+
const modal = createModal(this.requireComponent('loading-modal'), props);
|
|
250
|
+
|
|
251
|
+
showModal(modal);
|
|
257
252
|
|
|
258
253
|
try {
|
|
259
254
|
const result = await operationPromise;
|
|
@@ -262,7 +257,7 @@ export class UIService extends Service {
|
|
|
262
257
|
|
|
263
258
|
return result;
|
|
264
259
|
} finally {
|
|
265
|
-
await
|
|
260
|
+
await closeModal(modal.id, { removeAfter: 1000 });
|
|
266
261
|
}
|
|
267
262
|
}
|
|
268
263
|
|
|
@@ -278,98 +273,29 @@ export class UIService extends Service {
|
|
|
278
273
|
}
|
|
279
274
|
|
|
280
275
|
public modal<T extends Component>(
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
): Promise<UIModal<ModalResult<T>>>;
|
|
285
|
-
|
|
286
|
-
public async modal<T extends Component>(component: T, props?: ComponentProps<T>): Promise<UIModal<ModalResult<T>>> {
|
|
287
|
-
const id = uuid();
|
|
288
|
-
const callbacks: Partial<ModalCallbacks<ModalResult<T>>> = {};
|
|
289
|
-
const modal: UIModal<ModalResult<T>> = {
|
|
290
|
-
id,
|
|
291
|
-
closing: false,
|
|
292
|
-
properties: props ?? {},
|
|
293
|
-
component: markRaw(component),
|
|
294
|
-
beforeClose: new Promise((resolve) => (callbacks.willClose = resolve)),
|
|
295
|
-
afterClose: new Promise((resolve) => (callbacks.hasClosed = resolve)),
|
|
296
|
-
};
|
|
297
|
-
const modals = this.modals.concat(modal);
|
|
298
|
-
|
|
299
|
-
this.modalCallbacks[modal.id] = callbacks;
|
|
300
|
-
|
|
301
|
-
this.setState({ modals });
|
|
302
|
-
|
|
303
|
-
await nextTick();
|
|
304
|
-
|
|
305
|
-
return modal;
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
public modalForm<T extends Component>(
|
|
309
|
-
...args: {} extends ComponentProps<T>
|
|
310
|
-
? [component: T, props?: AcceptRefs<ComponentProps<T>>]
|
|
311
|
-
: [component: T, props: AcceptRefs<ComponentProps<T>>]
|
|
312
|
-
): Promise<ModalResult<T> | undefined>;
|
|
276
|
+
component: T & object extends GetModalProps<T> ? T : never,
|
|
277
|
+
props?: GetModalProps<T>
|
|
278
|
+
): Promise<GetModalResponse<T>>;
|
|
313
279
|
|
|
314
|
-
public
|
|
315
|
-
component: T,
|
|
316
|
-
props
|
|
317
|
-
): Promise<
|
|
318
|
-
const modal = await this.modal<T>(component, props as ComponentProps<T>);
|
|
319
|
-
const result = await modal.beforeClose;
|
|
320
|
-
|
|
321
|
-
return result;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
public async closeModal(id: string, result?: unknown): Promise<void> {
|
|
325
|
-
if (!App.isMounted()) {
|
|
326
|
-
await this.removeModal(id, result);
|
|
327
|
-
|
|
328
|
-
return;
|
|
329
|
-
}
|
|
280
|
+
public modal<T extends Component>(
|
|
281
|
+
component: T & object extends GetModalProps<T> ? never : T,
|
|
282
|
+
props: GetModalProps<T>
|
|
283
|
+
): Promise<GetModalResponse<T>>;
|
|
330
284
|
|
|
331
|
-
|
|
285
|
+
public modal<T extends Component>(component: T, componentProps?: GetModalProps<T>): Promise<GetModalResponse<T>> {
|
|
286
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
287
|
+
return showModal(component as any, componentProps ?? {}) as Promise<GetModalResponse<T>>;
|
|
332
288
|
}
|
|
333
289
|
|
|
334
290
|
public async closeAllModals(): Promise<void> {
|
|
335
|
-
|
|
336
|
-
await this.closeModal(required(this.modals[this.modals.length - 1]).id);
|
|
337
|
-
}
|
|
291
|
+
await Promise.all(modals.value.map(({ id }) => closeModal(id, { removeAfter: 1000 })));
|
|
338
292
|
}
|
|
339
293
|
|
|
340
294
|
protected override async boot(): Promise<void> {
|
|
341
|
-
this.watchModalEvents();
|
|
342
295
|
this.watchMountedEvent();
|
|
343
296
|
this.watchViewportBreakpoints();
|
|
344
297
|
}
|
|
345
298
|
|
|
346
|
-
private async removeModal(id: string, result?: unknown): Promise<void> {
|
|
347
|
-
this.setState(
|
|
348
|
-
'modals',
|
|
349
|
-
this.modals.filter((m) => m.id !== id),
|
|
350
|
-
);
|
|
351
|
-
|
|
352
|
-
this.modalCallbacks[id]?.hasClosed?.(result);
|
|
353
|
-
|
|
354
|
-
delete this.modalCallbacks[id];
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
private watchModalEvents(): void {
|
|
358
|
-
Events.on('modal-will-close', ({ modal: { id }, result }) => {
|
|
359
|
-
const modal = this.modals.find((_modal) => id === _modal.id);
|
|
360
|
-
|
|
361
|
-
if (modal) {
|
|
362
|
-
modal.closing = true;
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
this.modalCallbacks[id]?.willClose?.(result);
|
|
366
|
-
});
|
|
367
|
-
|
|
368
|
-
Events.on('modal-has-closed', async ({ modal: { id }, result }) => {
|
|
369
|
-
await this.removeModal(id, result);
|
|
370
|
-
});
|
|
371
|
-
}
|
|
372
|
-
|
|
373
299
|
private watchMountedEvent(): void {
|
|
374
300
|
Events.once('application-mounted', async () => {
|
|
375
301
|
if (!globalThis.document || !globalThis.getComputedStyle) {
|
|
@@ -405,11 +331,3 @@ export class UIService extends Service {
|
|
|
405
331
|
}
|
|
406
332
|
|
|
407
333
|
export default facade(UIService);
|
|
408
|
-
|
|
409
|
-
declare module '@aerogel/core/services/Events' {
|
|
410
|
-
export interface EventsPayload {
|
|
411
|
-
'close-modal': { id: string; result?: unknown };
|
|
412
|
-
'modal-will-close': { modal: UIModal; result?: unknown };
|
|
413
|
-
'modal-has-closed': { modal: UIModal; result?: unknown };
|
|
414
|
-
}
|
|
415
|
-
}
|
package/src/ui/index.ts
CHANGED
package/src/ui/modals.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { after } from '@noeldemartin/utils';
|
|
2
|
+
import { injectModal, useModal as useModalBase } from '@noeldemartin/vue-modals';
|
|
3
|
+
|
|
4
|
+
export {
|
|
5
|
+
createModal,
|
|
6
|
+
showModal,
|
|
7
|
+
injectModal,
|
|
8
|
+
closeModal,
|
|
9
|
+
modals,
|
|
10
|
+
ModalComponent,
|
|
11
|
+
ModalsPortal,
|
|
12
|
+
type GetModalProps,
|
|
13
|
+
type GetModalResponse,
|
|
14
|
+
type ModalController,
|
|
15
|
+
} from '@noeldemartin/vue-modals';
|
|
16
|
+
|
|
17
|
+
const instances = new WeakSet();
|
|
18
|
+
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
20
|
+
export function useModal<T = never>() {
|
|
21
|
+
const instance = injectModal<T>();
|
|
22
|
+
const { close, remove, ...modal } = useModalBase<T>(instances.has(instance) ? {} : { removeOnClose: false });
|
|
23
|
+
|
|
24
|
+
instances.add(instance);
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
...modal,
|
|
28
|
+
async close(result?: T) {
|
|
29
|
+
close(result);
|
|
30
|
+
|
|
31
|
+
await after(1000);
|
|
32
|
+
|
|
33
|
+
remove();
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
}
|
package/src/utils/classes.ts
CHANGED
|
@@ -4,10 +4,9 @@ import { cva } from 'class-variance-authority';
|
|
|
4
4
|
import { twMerge } from 'tailwind-merge';
|
|
5
5
|
import type { ClassValue } from 'clsx';
|
|
6
6
|
import type { PropType } from 'vue';
|
|
7
|
-
import type { GetClosureArgs, GetClosureResult } from '@noeldemartin/utils';
|
|
8
7
|
|
|
9
|
-
export type CVAConfig<T> = NonNullable<
|
|
10
|
-
export type CVAProps<T> = NonNullable<
|
|
8
|
+
export type CVAConfig<T> = NonNullable<Parameters<typeof cva<T>>[1]>;
|
|
9
|
+
export type CVAProps<T> = NonNullable<Parameters<ReturnType<typeof cva<T>>>[0]>;
|
|
11
10
|
export type Variants<T extends Record<string, string | boolean>> = Required<{
|
|
12
11
|
[K in keyof T]: Exclude<T[K], undefined> extends string
|
|
13
12
|
? { [key in Exclude<T[K], undefined>]: string | null }
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { nextTick, watchEffect } from 'vue';
|
|
3
|
+
|
|
4
|
+
import { reactiveSet } from './reactiveSet';
|
|
5
|
+
|
|
6
|
+
describe('Vue reactiveSet', () => {
|
|
7
|
+
|
|
8
|
+
it('watches updates', async () => {
|
|
9
|
+
// Arrange
|
|
10
|
+
const set = reactiveSet();
|
|
11
|
+
let updates = 0;
|
|
12
|
+
|
|
13
|
+
watchEffect(() => (set.has('foo'), updates++));
|
|
14
|
+
|
|
15
|
+
// Act
|
|
16
|
+
set.add('foo');
|
|
17
|
+
await nextTick();
|
|
18
|
+
|
|
19
|
+
set.add('bar');
|
|
20
|
+
await nextTick();
|
|
21
|
+
|
|
22
|
+
set.add('baz');
|
|
23
|
+
await nextTick();
|
|
24
|
+
|
|
25
|
+
set.reset();
|
|
26
|
+
await nextTick();
|
|
27
|
+
|
|
28
|
+
// Assert
|
|
29
|
+
expect(updates).toEqual(5);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
});
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { fail } from '@noeldemartin/utils';
|
|
2
|
+
import { customRef } from 'vue';
|
|
3
|
+
|
|
4
|
+
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
5
|
+
export function reactiveSet<T>(initial?: T[] | Set<T>, options: { equals?: (a: T, b: T) => boolean } = {}) {
|
|
6
|
+
let set: Set<T> = new Set(initial);
|
|
7
|
+
let trigger: () => void;
|
|
8
|
+
let track: () => void;
|
|
9
|
+
const equals = options?.equals;
|
|
10
|
+
const hasEqual = equals
|
|
11
|
+
? (item: T) => ref.value.values().some((existingItem) => equals(item, existingItem))
|
|
12
|
+
: () => false;
|
|
13
|
+
const ref = customRef((_track, _trigger) => {
|
|
14
|
+
track = _track;
|
|
15
|
+
trigger = _trigger;
|
|
16
|
+
|
|
17
|
+
return {
|
|
18
|
+
get: () => set,
|
|
19
|
+
set: () => fail('Attempted to write read-only reactive set'),
|
|
20
|
+
};
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
return {
|
|
24
|
+
values() {
|
|
25
|
+
track();
|
|
26
|
+
|
|
27
|
+
return Array.from(ref.value.values());
|
|
28
|
+
},
|
|
29
|
+
has(item: T) {
|
|
30
|
+
track();
|
|
31
|
+
|
|
32
|
+
return ref.value.has(item) || hasEqual(item);
|
|
33
|
+
},
|
|
34
|
+
add(item: T) {
|
|
35
|
+
trigger();
|
|
36
|
+
|
|
37
|
+
if (hasEqual(item)) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
ref.value.add(item);
|
|
42
|
+
},
|
|
43
|
+
delete(item: T) {
|
|
44
|
+
trigger();
|
|
45
|
+
|
|
46
|
+
ref.value.delete(item);
|
|
47
|
+
},
|
|
48
|
+
clear() {
|
|
49
|
+
trigger();
|
|
50
|
+
|
|
51
|
+
ref.value.clear();
|
|
52
|
+
},
|
|
53
|
+
reset(items?: T[] | Set<T>) {
|
|
54
|
+
trigger();
|
|
55
|
+
|
|
56
|
+
set = new Set(items);
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export type ReactiveSet<T = unknown> = ReturnType<typeof reactiveSet<T>>;
|
package/src/utils/index.ts
CHANGED
|
@@ -4,7 +4,9 @@ export * from './composition/events';
|
|
|
4
4
|
export * from './composition/forms';
|
|
5
5
|
export * from './composition/hooks';
|
|
6
6
|
export * from './composition/persistent';
|
|
7
|
+
export * from './composition/reactiveSet';
|
|
7
8
|
export * from './composition/state';
|
|
8
9
|
export * from './markdown';
|
|
10
|
+
export * from './time';
|
|
9
11
|
export * from './types';
|
|
10
12
|
export * from './vue';
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<aside v-if="modal">
|
|
3
|
-
<ModalContext :child-index="1" :modal />
|
|
4
|
-
</aside>
|
|
5
|
-
</template>
|
|
6
|
-
|
|
7
|
-
<script setup lang="ts">
|
|
8
|
-
import { computed } from 'vue';
|
|
9
|
-
|
|
10
|
-
import ModalContext from '@aerogel/core/components/ui/ModalContext.vue';
|
|
11
|
-
import UI from '@aerogel/core/ui/UI';
|
|
12
|
-
|
|
13
|
-
const modal = computed(() => UI.modals[0] ?? null);
|
|
14
|
-
</script>
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<component :is="modal.component" v-bind="modalProperties" />
|
|
3
|
-
</template>
|
|
4
|
-
|
|
5
|
-
<script setup lang="ts">
|
|
6
|
-
import { computed, provide, toRef, unref } from 'vue';
|
|
7
|
-
|
|
8
|
-
import type { UIModal } from '@aerogel/core/ui/UI.state';
|
|
9
|
-
import type { UIModalContext } from '@aerogel/core/ui/UI';
|
|
10
|
-
import type { AcceptRefs } from '@aerogel/core/utils/vue';
|
|
11
|
-
|
|
12
|
-
const props = defineProps<{
|
|
13
|
-
modal: UIModal;
|
|
14
|
-
childIndex?: number;
|
|
15
|
-
}>();
|
|
16
|
-
|
|
17
|
-
const modalProperties = computed(() => {
|
|
18
|
-
const properties = {} as typeof props.modal.properties;
|
|
19
|
-
|
|
20
|
-
for (const property in props.modal.properties) {
|
|
21
|
-
properties[property] = unref(props.modal.properties[property]);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
return properties;
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
provide<AcceptRefs<UIModalContext>>('modal', {
|
|
28
|
-
modal: toRef(props, 'modal'),
|
|
29
|
-
childIndex: toRef(props, 'childIndex'),
|
|
30
|
-
});
|
|
31
|
-
</script>
|