@soave/nuxt-ui 0.1.0

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 (35) hide show
  1. package/dist/module.cjs +5 -0
  2. package/dist/module.d.mts +25 -0
  3. package/dist/module.d.ts +25 -0
  4. package/dist/module.json +12 -0
  5. package/dist/module.mjs +52 -0
  6. package/dist/runtime/components/Breadcrumbs.vue +78 -0
  7. package/dist/runtime/components/DataTable.vue +334 -0
  8. package/dist/runtime/components/Pagination.vue +154 -0
  9. package/dist/runtime/components/Table.vue +18 -0
  10. package/dist/runtime/components/TableBody.vue +15 -0
  11. package/dist/runtime/components/TableCell.vue +20 -0
  12. package/dist/runtime/components/TableHead.vue +44 -0
  13. package/dist/runtime/components/TableHeader.vue +15 -0
  14. package/dist/runtime/components/TableRow.vue +25 -0
  15. package/dist/runtime/components/index.d.ts +0 -0
  16. package/dist/runtime/components/index.js +9 -0
  17. package/dist/runtime/composables/index.d.ts +0 -0
  18. package/dist/runtime/composables/index.js +20 -0
  19. package/dist/runtime/composables/useBreadcrumbs.d.ts +0 -0
  20. package/dist/runtime/composables/useBreadcrumbs.js +75 -0
  21. package/dist/runtime/composables/useI18nUI.d.ts +0 -0
  22. package/dist/runtime/composables/useI18nUI.js +105 -0
  23. package/dist/runtime/composables/usePagination.d.ts +0 -0
  24. package/dist/runtime/composables/usePagination.js +114 -0
  25. package/dist/runtime/composables/useSoaveSeoMeta.d.ts +0 -0
  26. package/dist/runtime/composables/useSoaveSeoMeta.js +130 -0
  27. package/dist/runtime/composables/useTypedRoute.d.ts +0 -0
  28. package/dist/runtime/composables/useTypedRoute.js +22 -0
  29. package/dist/runtime/plugins/ui-provider.client.d.ts +0 -0
  30. package/dist/runtime/plugins/ui-provider.client.js +10 -0
  31. package/dist/runtime/plugins/ui-provider.server.d.ts +0 -0
  32. package/dist/runtime/plugins/ui-provider.server.js +10 -0
  33. package/dist/types.d.mts +7 -0
  34. package/dist/types.d.ts +7 -0
  35. package/package.json +52 -0
@@ -0,0 +1,18 @@
1
+ <template>
2
+ <div :class="cn('relative w-full overflow-auto', wrapper_class)">
3
+ <table :class="cn('w-full caption-bottom text-sm', props.class)">
4
+ <slot />
5
+ </table>
6
+ </div>
7
+ </template>
8
+
9
+ <script setup lang="ts">
10
+ import { cn } from "@soave/ui"
11
+
12
+ export interface TableProps {
13
+ class?: string
14
+ wrapper_class?: string
15
+ }
16
+
17
+ const props = defineProps<TableProps>()
18
+ </script>
@@ -0,0 +1,15 @@
1
+ <template>
2
+ <tbody :class="cn('[&_tr:last-child]:border-0', props.class)">
3
+ <slot />
4
+ </tbody>
5
+ </template>
6
+
7
+ <script setup lang="ts">
8
+ import { cn } from "@soave/ui"
9
+
10
+ export interface TableBodyProps {
11
+ class?: string
12
+ }
13
+
14
+ const props = defineProps<TableBodyProps>()
15
+ </script>
@@ -0,0 +1,20 @@
1
+ <template>
2
+ <td
3
+ :class="cn(
4
+ 'p-4 align-middle [&:has([role=checkbox])]:pr-0',
5
+ props.class
6
+ )"
7
+ >
8
+ <slot />
9
+ </td>
10
+ </template>
11
+
12
+ <script setup lang="ts">
13
+ import { cn } from "@soave/ui"
14
+
15
+ export interface TableCellProps {
16
+ class?: string
17
+ }
18
+
19
+ const props = defineProps<TableCellProps>()
20
+ </script>
@@ -0,0 +1,44 @@
1
+ <template>
2
+ <th
3
+ :class="cn(
4
+ 'h-10 px-4 text-left align-middle font-medium text-muted-foreground',
5
+ '[&:has([role=checkbox])]:pr-0',
6
+ sortable && 'cursor-pointer select-none hover:text-foreground',
7
+ props.class
8
+ )"
9
+ :aria-sort="sort_direction ? (sort_direction === 'asc' ? 'ascending' : 'descending') : undefined"
10
+ @click="handleClick"
11
+ >
12
+ <div class="flex items-center gap-2">
13
+ <slot />
14
+ <span v-if="sortable && sort_direction" aria-hidden="true">
15
+ {{ sort_direction === "asc" ? "↑" : "↓" }}
16
+ </span>
17
+ </div>
18
+ </th>
19
+ </template>
20
+
21
+ <script setup lang="ts">
22
+ import { cn } from "@soave/ui"
23
+
24
+ export interface TableHeadProps {
25
+ sortable?: boolean
26
+ sort_direction?: "asc" | "desc" | null
27
+ class?: string
28
+ }
29
+
30
+ const props = withDefaults(defineProps<TableHeadProps>(), {
31
+ sortable: false,
32
+ sort_direction: null
33
+ })
34
+
35
+ const emit = defineEmits<{
36
+ sort: []
37
+ }>()
38
+
39
+ const handleClick = (): void => {
40
+ if (props.sortable) {
41
+ emit("sort")
42
+ }
43
+ }
44
+ </script>
@@ -0,0 +1,15 @@
1
+ <template>
2
+ <thead :class="cn('[&_tr]:border-b', props.class)">
3
+ <slot />
4
+ </thead>
5
+ </template>
6
+
7
+ <script setup lang="ts">
8
+ import { cn } from "@soave/ui"
9
+
10
+ export interface TableHeaderProps {
11
+ class?: string
12
+ }
13
+
14
+ const props = defineProps<TableHeaderProps>()
15
+ </script>
@@ -0,0 +1,25 @@
1
+ <template>
2
+ <tr
3
+ :class="cn(
4
+ 'border-b transition-colors hover:bg-muted/50',
5
+ selected && 'bg-muted',
6
+ props.class
7
+ )"
8
+ :data-state="selected ? 'selected' : undefined"
9
+ >
10
+ <slot />
11
+ </tr>
12
+ </template>
13
+
14
+ <script setup lang="ts">
15
+ import { cn } from "@soave/ui"
16
+
17
+ export interface TableRowProps {
18
+ selected?: boolean
19
+ class?: string
20
+ }
21
+
22
+ const props = withDefaults(defineProps<TableRowProps>(), {
23
+ selected: false
24
+ })
25
+ </script>
File without changes
@@ -0,0 +1,9 @@
1
+ export { default as Breadcrumbs } from "./Breadcrumbs.vue";
2
+ export { default as Pagination } from "./Pagination.vue";
3
+ export { default as Table } from "./Table.vue";
4
+ export { default as TableHeader } from "./TableHeader.vue";
5
+ export { default as TableBody } from "./TableBody.vue";
6
+ export { default as TableRow } from "./TableRow.vue";
7
+ export { default as TableHead } from "./TableHead.vue";
8
+ export { default as TableCell } from "./TableCell.vue";
9
+ export { default as DataTable } from "./DataTable.vue";
File without changes
@@ -0,0 +1,20 @@
1
+ export {
2
+ defineRoute,
3
+ useTypedParams,
4
+ useTypedQuery,
5
+ useParam,
6
+ useQueryParam
7
+ } from "./useTypedRoute.js";
8
+ export {
9
+ useBreadcrumbs
10
+ } from "./useBreadcrumbs.js";
11
+ export {
12
+ useSoaveSeoMeta,
13
+ useStructuredData
14
+ } from "./useSoaveSeoMeta.js";
15
+ export { usePagination } from "./usePagination.js";
16
+ export {
17
+ useI18nUI,
18
+ createUITranslations,
19
+ getDefaultTranslations
20
+ } from "./useI18nUI.js";
File without changes
@@ -0,0 +1,75 @@
1
+ import { useRoute } from "#app";
2
+ import { computed, ref } from "vue";
3
+ const default_label_transformer = (segment) => {
4
+ return segment.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
5
+ };
6
+ export function useBreadcrumbs(options = {}) {
7
+ const route = useRoute();
8
+ const {
9
+ home_label = "Home",
10
+ home_href = "/",
11
+ home_icon,
12
+ include_home = true,
13
+ label_transformer = default_label_transformer,
14
+ custom_labels = {}
15
+ } = options;
16
+ const manual_items = ref(null);
17
+ const auto_breadcrumbs = computed(() => {
18
+ const path_segments = route.path.split("/").filter(Boolean);
19
+ const items = [];
20
+ if (include_home) {
21
+ items.push({
22
+ label: home_label,
23
+ href: home_href,
24
+ icon: home_icon,
25
+ current: path_segments.length === 0
26
+ });
27
+ }
28
+ let accumulated_path = "";
29
+ path_segments.forEach((segment, index) => {
30
+ if (segment.startsWith("[") && segment.endsWith("]")) {
31
+ const param_name = segment.slice(1, -1);
32
+ const param_value = route.params[param_name];
33
+ if (param_value) {
34
+ segment = String(param_value);
35
+ }
36
+ }
37
+ accumulated_path += `/${segment}`;
38
+ const is_last = index === path_segments.length - 1;
39
+ const label = custom_labels[segment] || custom_labels[accumulated_path] || label_transformer(segment);
40
+ items.push({
41
+ label,
42
+ href: is_last ? void 0 : accumulated_path,
43
+ current: is_last,
44
+ disabled: is_last
45
+ });
46
+ });
47
+ return items;
48
+ });
49
+ const breadcrumbs = computed(() => {
50
+ return manual_items.value ?? auto_breadcrumbs.value;
51
+ });
52
+ const current = computed(() => {
53
+ return breadcrumbs.value.find((item) => item.current);
54
+ });
55
+ const set = (items) => {
56
+ manual_items.value = items;
57
+ };
58
+ const append = (item) => {
59
+ if (manual_items.value) {
60
+ manual_items.value = [...manual_items.value, item];
61
+ } else {
62
+ manual_items.value = [...auto_breadcrumbs.value, item];
63
+ }
64
+ };
65
+ const reset = () => {
66
+ manual_items.value = null;
67
+ };
68
+ return {
69
+ breadcrumbs,
70
+ current,
71
+ set,
72
+ append,
73
+ reset
74
+ };
75
+ }
File without changes
@@ -0,0 +1,105 @@
1
+ import { computed, toValue } from "vue";
2
+ const DEFAULT_TRANSLATIONS = {
3
+ pagination: {
4
+ previous: "Previous",
5
+ next: "Next",
6
+ first: "First",
7
+ last: "Last",
8
+ page: "Page",
9
+ showing: "Showing",
10
+ of: "of",
11
+ results: "results"
12
+ },
13
+ data_table: {
14
+ no_results: "No results found.",
15
+ select_all: "Select all",
16
+ select_row: "Select row",
17
+ actions: "Actions",
18
+ loading: "Loading...",
19
+ sort_ascending: "Sort ascending",
20
+ sort_descending: "Sort descending"
21
+ },
22
+ breadcrumbs: {
23
+ home: "Home",
24
+ navigation: "Breadcrumb"
25
+ },
26
+ common: {
27
+ loading: "Loading...",
28
+ error: "An error occurred",
29
+ empty: "No data available",
30
+ cancel: "Cancel",
31
+ confirm: "Confirm",
32
+ save: "Save",
33
+ delete: "Delete",
34
+ edit: "Edit",
35
+ create: "Create",
36
+ search: "Search",
37
+ filter: "Filter",
38
+ clear: "Clear",
39
+ close: "Close",
40
+ open: "Open",
41
+ submit: "Submit",
42
+ reset: "Reset"
43
+ }
44
+ };
45
+ let nuxt_i18n_available = false;
46
+ let use_i18n_function = null;
47
+ try {
48
+ const i18n_module = import.meta.glob("/node_modules/@nuxtjs/i18n/**/*.js", { eager: false });
49
+ nuxt_i18n_available = Object.keys(i18n_module).length > 0;
50
+ } catch {
51
+ nuxt_i18n_available = false;
52
+ }
53
+ export function useI18nUI(options = {}) {
54
+ const { translations: custom_translations = {}, use_nuxt_i18n = nuxt_i18n_available } = options;
55
+ const merged_translations = mergeDeep(DEFAULT_TRANSLATIONS, custom_translations);
56
+ const t = (namespace, key) => {
57
+ return computed(() => {
58
+ if (use_nuxt_i18n && use_i18n_function) {
59
+ const i18n = use_i18n_function();
60
+ const i18n_key = `soave_ui.${namespace}.${String(key)}`;
61
+ const translated = i18n.t(i18n_key);
62
+ if (translated !== i18n_key) {
63
+ return translated;
64
+ }
65
+ }
66
+ const namespace_translations = merged_translations[namespace];
67
+ if (namespace_translations && key in namespace_translations) {
68
+ return namespace_translations[key];
69
+ }
70
+ return String(key);
71
+ });
72
+ };
73
+ return {
74
+ t,
75
+ translations: merged_translations
76
+ };
77
+ }
78
+ export function createUITranslations(translations) {
79
+ const resolved = toValue(translations);
80
+ return mergeDeep(DEFAULT_TRANSLATIONS, resolved);
81
+ }
82
+ export function getDefaultTranslations() {
83
+ return { ...DEFAULT_TRANSLATIONS };
84
+ }
85
+ function mergeDeep(target, source) {
86
+ const output = { ...target };
87
+ for (const key in source) {
88
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
89
+ const source_value = source[key];
90
+ const target_value = output[key];
91
+ if (isObject(source_value) && isObject(target_value)) {
92
+ output[key] = mergeDeep(
93
+ target_value,
94
+ source_value
95
+ );
96
+ } else if (source_value !== void 0) {
97
+ output[key] = source_value;
98
+ }
99
+ }
100
+ }
101
+ return output;
102
+ }
103
+ function isObject(item) {
104
+ return item !== null && typeof item === "object" && !Array.isArray(item);
105
+ }
File without changes
@@ -0,0 +1,114 @@
1
+ import { computed, ref } from "vue";
2
+ export function usePagination(options = {}) {
3
+ const {
4
+ initial_page = 1,
5
+ per_page: initial_per_page = 10,
6
+ total_items: initial_total_items = 0,
7
+ sibling_count = 1,
8
+ boundary_count = 1
9
+ } = options;
10
+ const current_page = ref(initial_page);
11
+ const per_page = ref(initial_per_page);
12
+ const total_items = ref(initial_total_items);
13
+ const total_pages = computed(() => {
14
+ return Math.max(1, Math.ceil(total_items.value / per_page.value));
15
+ });
16
+ const has_previous = computed(() => current_page.value > 1);
17
+ const has_next = computed(() => current_page.value < total_pages.value);
18
+ const state = computed(() => ({
19
+ current_page: current_page.value,
20
+ total_pages: total_pages.value,
21
+ total_items: total_items.value,
22
+ per_page: per_page.value,
23
+ has_previous: has_previous.value,
24
+ has_next: has_next.value
25
+ }));
26
+ const pages = computed(() => {
27
+ const total = total_pages.value;
28
+ const current = current_page.value;
29
+ const result = [];
30
+ const start_pages = range(1, Math.min(boundary_count, total));
31
+ const end_pages = range(Math.max(total - boundary_count + 1, boundary_count + 1), total);
32
+ const sibling_start = Math.max(
33
+ Math.min(
34
+ current - sibling_count,
35
+ total - boundary_count - sibling_count * 2 - 1
36
+ ),
37
+ boundary_count + 2
38
+ );
39
+ const sibling_end = Math.min(
40
+ Math.max(
41
+ current + sibling_count,
42
+ boundary_count + sibling_count * 2 + 2
43
+ ),
44
+ end_pages.length > 0 ? end_pages[0] - 2 : total - 1
45
+ );
46
+ result.push(...start_pages);
47
+ if (sibling_start > boundary_count + 2) {
48
+ result.push("ellipsis");
49
+ } else if (boundary_count + 1 < total - boundary_count) {
50
+ result.push(boundary_count + 1);
51
+ }
52
+ result.push(...range(sibling_start, sibling_end));
53
+ if (sibling_end < total - boundary_count - 1) {
54
+ result.push("ellipsis");
55
+ } else if (total - boundary_count > boundary_count) {
56
+ result.push(total - boundary_count);
57
+ }
58
+ result.push(...end_pages);
59
+ const unique = [...new Set(result.filter((p) => p === "ellipsis" || p >= 1 && p <= total))];
60
+ return unique;
61
+ });
62
+ const setPage = (page) => {
63
+ if (page >= 1 && page <= total_pages.value) {
64
+ current_page.value = page;
65
+ }
66
+ };
67
+ const nextPage = () => {
68
+ if (has_next.value) {
69
+ current_page.value++;
70
+ }
71
+ };
72
+ const previousPage = () => {
73
+ if (has_previous.value) {
74
+ current_page.value--;
75
+ }
76
+ };
77
+ const firstPage = () => {
78
+ current_page.value = 1;
79
+ };
80
+ const lastPage = () => {
81
+ current_page.value = total_pages.value;
82
+ };
83
+ const setPerPage = (count) => {
84
+ per_page.value = count;
85
+ current_page.value = 1;
86
+ };
87
+ const setTotalItems = (count) => {
88
+ total_items.value = count;
89
+ if (current_page.value > total_pages.value) {
90
+ current_page.value = total_pages.value;
91
+ }
92
+ };
93
+ return {
94
+ state,
95
+ current_page,
96
+ per_page,
97
+ total_items,
98
+ pages,
99
+ setPage,
100
+ nextPage,
101
+ previousPage,
102
+ firstPage,
103
+ lastPage,
104
+ setPerPage,
105
+ setTotalItems
106
+ };
107
+ }
108
+ function range(start, end) {
109
+ const result = [];
110
+ for (let i = start; i <= end; i++) {
111
+ result.push(i);
112
+ }
113
+ return result;
114
+ }
File without changes
@@ -0,0 +1,130 @@
1
+ import { useSeoMeta as useNuxtSeoMeta, useHead } from "#app";
2
+ import { computed, toValue } from "vue";
3
+ export function useSoaveSeoMeta(options) {
4
+ const title = computed(() => toValue(options.title));
5
+ const description = computed(() => toValue(options.description));
6
+ const image = computed(() => toValue(options.image));
7
+ const url = computed(() => toValue(options.url));
8
+ const type = computed(() => toValue(options.type) || "website");
9
+ const site_name = computed(() => toValue(options.site_name));
10
+ const locale = computed(() => toValue(options.locale));
11
+ const twitter_card = computed(() => toValue(options.twitter_card) || "summary_large_image");
12
+ const author = computed(() => toValue(options.author));
13
+ const keywords = computed(() => toValue(options.keywords));
14
+ const robots = computed(() => toValue(options.robots));
15
+ useNuxtSeoMeta({
16
+ title,
17
+ description,
18
+ ogTitle: title,
19
+ ogDescription: description,
20
+ ogImage: image,
21
+ ogUrl: url,
22
+ ogType: type,
23
+ ogSiteName: site_name,
24
+ ogLocale: locale,
25
+ twitterCard: twitter_card,
26
+ twitterTitle: title,
27
+ twitterDescription: description,
28
+ twitterImage: image,
29
+ author,
30
+ robots
31
+ });
32
+ if (options.keywords) {
33
+ useHead({
34
+ meta: [
35
+ {
36
+ name: "keywords",
37
+ content: keywords
38
+ }
39
+ ]
40
+ });
41
+ }
42
+ if (options.published_time || options.modified_time) {
43
+ useHead({
44
+ meta: [
45
+ ...options.published_time ? [{
46
+ property: "article:published_time",
47
+ content: computed(() => toValue(options.published_time))
48
+ }] : [],
49
+ ...options.modified_time ? [{
50
+ property: "article:modified_time",
51
+ content: computed(() => toValue(options.modified_time))
52
+ }] : []
53
+ ]
54
+ });
55
+ }
56
+ }
57
+ export function useStructuredData(options) {
58
+ const scripts = [];
59
+ if (options.breadcrumbs && options.breadcrumbs.length > 0) {
60
+ const breadcrumb_list = {
61
+ "@context": "https://schema.org",
62
+ "@type": "BreadcrumbList",
63
+ "itemListElement": options.breadcrumbs.map((item, index) => ({
64
+ "@type": "ListItem",
65
+ "position": index + 1,
66
+ "name": item.name,
67
+ "item": item.url
68
+ }))
69
+ };
70
+ scripts.push({
71
+ type: "application/ld+json",
72
+ innerHTML: JSON.stringify(breadcrumb_list)
73
+ });
74
+ }
75
+ if (options.article) {
76
+ const article = {
77
+ "@context": "https://schema.org",
78
+ "@type": "Article",
79
+ "headline": options.article.headline,
80
+ "author": {
81
+ "@type": "Person",
82
+ "name": options.article.author
83
+ },
84
+ "datePublished": options.article.published_date,
85
+ ...options.article.modified_date && { "dateModified": options.article.modified_date },
86
+ ...options.article.image && { "image": options.article.image }
87
+ };
88
+ scripts.push({
89
+ type: "application/ld+json",
90
+ innerHTML: JSON.stringify(article)
91
+ });
92
+ }
93
+ if (options.organization) {
94
+ const organization = {
95
+ "@context": "https://schema.org",
96
+ "@type": "Organization",
97
+ "name": options.organization.name,
98
+ "url": options.organization.url,
99
+ ...options.organization.logo && { "logo": options.organization.logo }
100
+ };
101
+ scripts.push({
102
+ type: "application/ld+json",
103
+ innerHTML: JSON.stringify(organization)
104
+ });
105
+ }
106
+ if (options.product) {
107
+ const product = {
108
+ "@context": "https://schema.org",
109
+ "@type": "Product",
110
+ "name": options.product.name,
111
+ "description": options.product.description,
112
+ ...options.product.image && { "image": options.product.image },
113
+ "offers": {
114
+ "@type": "Offer",
115
+ "price": options.product.price,
116
+ "priceCurrency": options.product.currency,
117
+ ...options.product.availability && { "availability": `https://schema.org/${options.product.availability}` }
118
+ }
119
+ };
120
+ scripts.push({
121
+ type: "application/ld+json",
122
+ innerHTML: JSON.stringify(product)
123
+ });
124
+ }
125
+ if (scripts.length > 0) {
126
+ useHead({
127
+ script: scripts
128
+ });
129
+ }
130
+ }
File without changes
@@ -0,0 +1,22 @@
1
+ import { useRoute } from "#app";
2
+ import { computed } from "vue";
3
+ export function defineRoute() {
4
+ const route = useRoute();
5
+ return route;
6
+ }
7
+ export function useTypedParams() {
8
+ const route = useRoute();
9
+ return computed(() => route.params);
10
+ }
11
+ export function useTypedQuery() {
12
+ const route = useRoute();
13
+ return computed(() => route.query);
14
+ }
15
+ export function useParam(key) {
16
+ const route = useRoute();
17
+ return computed(() => route.params[key]);
18
+ }
19
+ export function useQueryParam(key) {
20
+ const route = useRoute();
21
+ return computed(() => route.query[key]);
22
+ }
File without changes
@@ -0,0 +1,10 @@
1
+ import { defineNuxtPlugin } from "#app";
2
+ import { useUIProvider } from "@soave/ui";
3
+ export default defineNuxtPlugin(() => {
4
+ const config = useUIProvider();
5
+ return {
6
+ provide: {
7
+ soaveUI: config
8
+ }
9
+ };
10
+ });
File without changes
@@ -0,0 +1,10 @@
1
+ import { defineNuxtPlugin } from "#app";
2
+ import { useUIProvider } from "@soave/ui";
3
+ export default defineNuxtPlugin(() => {
4
+ const config = useUIProvider();
5
+ return {
6
+ provide: {
7
+ soaveUI: config
8
+ }
9
+ };
10
+ });
@@ -0,0 +1,7 @@
1
+ import type { NuxtModule } from '@nuxt/schema'
2
+
3
+ import type { default as Module } from './module.js'
4
+
5
+ export type ModuleOptions = typeof Module extends NuxtModule<infer O> ? Partial<O> : Record<string, any>
6
+
7
+ export { default } from './module.js'
@@ -0,0 +1,7 @@
1
+ import type { NuxtModule } from '@nuxt/schema'
2
+
3
+ import type { default as Module } from './module'
4
+
5
+ export type ModuleOptions = typeof Module extends NuxtModule<infer O> ? Partial<O> : Record<string, any>
6
+
7
+ export { default } from './module'