stacks 0.47.4 → 0.48.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.
Files changed (116) hide show
  1. package/buddy/art/social.png +0 -0
  2. package/buddy/package.json +1 -1
  3. package/buddy/src/commands/make.ts +27 -12
  4. package/buddy/src/commands/test.ts +40 -2
  5. package/core/actions/package.json +2 -2
  6. package/core/actions/src/helpers/utils.ts +29 -3
  7. package/core/actions/src/make.ts +37 -6
  8. package/core/actions/src/test-coverage.ts +1 -1
  9. package/core/actions/src/test-feature.ts +5 -0
  10. package/core/actions/src/test-unit.ts +5 -0
  11. package/core/ai/package.json +1 -1
  12. package/core/alias/package.json +1 -1
  13. package/core/arrays/package.json +1 -1
  14. package/core/auth/package.json +1 -1
  15. package/core/build/package.json +3 -3
  16. package/core/cache/package.json +3 -3
  17. package/core/chat/README.md +33 -40
  18. package/core/chat/package.json +1 -1
  19. package/core/cli/package.json +1 -1
  20. package/core/cloud/package.json +1 -1
  21. package/core/collections/package.json +1 -1
  22. package/core/config/package.json +1 -1
  23. package/core/dashboard/package.json +1 -1
  24. package/core/database/package.json +1 -1
  25. package/core/datetime/package.json +1 -1
  26. package/core/desktop/package.json +1 -1
  27. package/core/docs/node_modules/.bin/vitepress +2 -2
  28. package/core/docs/package.json +2 -2
  29. package/core/domains/package.json +1 -1
  30. package/core/drivers/package.json +1 -1
  31. package/core/email/README.md +101 -35
  32. package/core/email/package.json +1 -1
  33. package/core/error-handling/package.json +2 -2
  34. package/core/events/package.json +1 -1
  35. package/core/git/package.json +1 -1
  36. package/core/health/package.json +1 -1
  37. package/core/lint/node_modules/.bin/eslint +2 -2
  38. package/core/lint/package.json +3 -3
  39. package/core/logging/package.json +1 -1
  40. package/core/modules/package.json +1 -1
  41. package/core/notifications/README.md +7 -2
  42. package/core/notifications/package.json +1 -1
  43. package/core/notifications/src/index.ts +37 -9
  44. package/core/notifications/tests/chat/Slack.test.ts +5 -4
  45. package/core/notifications/tests/email/Mailgun.test.ts +4 -3
  46. package/core/notifications/tests/email/Sendgrid.test.ts +3 -3
  47. package/core/notifications/tests/sms/Twilio.test.ts +3 -3
  48. package/core/objects/package.json +1 -1
  49. package/core/path/package.json +1 -1
  50. package/core/path/src/index.ts +5 -0
  51. package/core/payments/package.json +1 -1
  52. package/core/push/README.md +24 -42
  53. package/core/push/package.json +1 -1
  54. package/core/realtime/package.json +1 -1
  55. package/core/router/package.json +1 -1
  56. package/core/search-engine/package.json +1 -1
  57. package/core/security/package.json +1 -1
  58. package/core/server/package.json +1 -1
  59. package/core/sms/README.md +82 -35
  60. package/core/sms/package.json +1 -1
  61. package/core/storage/package.json +1 -1
  62. package/core/storage/src/index.ts +13 -0
  63. package/core/strings/README.md +10 -2
  64. package/core/strings/package.json +4 -2
  65. package/core/strings/src/case.ts +14 -0
  66. package/core/strings/src/index.ts +4 -97
  67. package/core/strings/src/pluralize.ts +1 -0
  68. package/core/strings/src/utils.ts +80 -0
  69. package/core/strings/src/validation.ts +182 -0
  70. package/core/tables/README.md +109 -0
  71. package/core/tables/examples/vue/App.vue +12 -0
  72. package/core/tables/examples/vue/favicon.png +0 -0
  73. package/core/tables/examples/vue/index.html +20 -0
  74. package/core/tables/examples/web/favicon.png +0 -0
  75. package/core/tables/examples/web/index.html +13 -0
  76. package/core/tables/node_modules/.bin/mkdist +17 -0
  77. package/core/tables/node_modules/.bin/tsc +17 -0
  78. package/core/tables/node_modules/.bin/tsserver +17 -0
  79. package/core/tables/node_modules/.bin/unbuild +17 -0
  80. package/core/tables/package.json +97 -0
  81. package/core/tables/src/cli/index.ts +1 -0
  82. package/core/tables/src/components/Demo.vue +89 -0
  83. package/core/tables/src/components/README.md +111 -0
  84. package/core/tables/src/components/Table.vue +342 -0
  85. package/core/tables/src/components/TableBody.vue +33 -0
  86. package/core/tables/src/components/TableCellActionItems.vue +9 -0
  87. package/core/tables/src/components/TableFilters.vue +703 -0
  88. package/core/tables/src/components/TableHead.vue +87 -0
  89. package/core/tables/src/components/TablePagination.vue +146 -0
  90. package/core/tables/src/components/TableRow.vue +78 -0
  91. package/core/tables/src/components/TableSearch.vue +38 -0
  92. package/core/tables/src/components/Tooltip.vue +10 -0
  93. package/core/tables/src/config/tables.ts +1 -0
  94. package/core/tables/src/docs/index.md +0 -0
  95. package/core/tables/src/functions/README.md +8 -0
  96. package/core/tables/src/functions/dark.ts +3 -0
  97. package/core/tables/src/functions/index.ts +2 -0
  98. package/core/tables/src/functions/table.ts +180 -0
  99. package/core/tables/tests/example.test.ts +7 -0
  100. package/core/testing/node_modules/.bin/vitest +2 -2
  101. package/core/testing/package.json +9 -6
  102. package/core/types/node_modules/.bin/vitepress +2 -2
  103. package/core/types/package.json +4 -3
  104. package/core/types/src/cli.ts +10 -2
  105. package/core/types/src/hashing.ts +15 -0
  106. package/core/types/src/index.ts +2 -0
  107. package/core/types/src/notifications.ts +1 -0
  108. package/core/types/src/reactivity.ts +3 -0
  109. package/core/types/src/tables.ts +48 -0
  110. package/core/ui/node_modules/.bin/vue-tsc +2 -2
  111. package/core/ui/package.json +2 -2
  112. package/core/utils/package.json +1 -1
  113. package/core/x-ray/package.json +1 -1
  114. package/package.json +3 -2
  115. package/tsconfig.json +8 -0
  116. package/vitest.config.ts +2 -0
@@ -0,0 +1,87 @@
1
+ <script setup lang="ts">
2
+ import { useTable } from '../table'
3
+
4
+ const { table, isColumnSortable, isColumnUsedAsSort, toggleSort, indeterminate, hits, lastColumn, readableLastColumn } = await useTable()
5
+ </script>
6
+
7
+ <template>
8
+ <thead class="bg-gray-50">
9
+ <tr>
10
+ <th
11
+ scope="col"
12
+ class="relative w-12 px-6 sm:px-8 sm:w-16"
13
+ >
14
+ <input
15
+ type="checkbox"
16
+ class="absolute w-4 h-4 -mt-2 text-indigo-600 border-gray-300 rounded top-1/2 left-4 sm:left-6 focus:ring-indigo-500"
17
+ :checked="indeterminate || table.selectedRows?.length === hits.length"
18
+ :indeterminate="indeterminate"
19
+ @change="table.selectedRows = ($event?.target as any).checked ? hits.map((h) => h.id) : []"
20
+ >
21
+ <!-- <input
22
+ type="checkbox"
23
+ class="absolute w-4 h-4 -mt-2 text-indigo-600 border-gray-300 rounded top-1/2 left-4 sm:left-6 focus:ring-indigo-500"
24
+ :checked="indeterminate || selectedRows?.length === hits?.length"
25
+ :indeterminate="indeterminate"
26
+ @change="selectedRows = []"
27
+ > -->
28
+ </th>
29
+
30
+ <th
31
+ v-for="(col, index) in table.columns"
32
+ :key="index"
33
+ scope="col"
34
+ class="font-semibold text-left text-sm py-3.5 pr-3 pl-4 sm:pl-6 text-gray-900"
35
+ :class="index === 0 ? `pr-3 pl-4 sm:pl-6` : `px-3`"
36
+ @click="toggleSort(col)"
37
+ >
38
+ <!-- the last column is oftentimes styled slightly different -->
39
+
40
+ <a
41
+ href="#"
42
+ class="inline-flex group"
43
+ >
44
+ {{ col.includes(':') ? col.split(':')[1].trim() : col }}
45
+ <span
46
+ v-if="isColumnSortable(col)"
47
+ class="flex-none ml-2 rounded"
48
+ :class="isColumnUsedAsSort(col) ? `bg-gray-200 text-gray-900 group-hover:bg-gray-300` : `text-gray-400 invisible group-hover:visible group-focus:visible`"
49
+ @click="toggleSort(col)"
50
+ >
51
+ <div
52
+ v-if="table.sort?.includes('desc')"
53
+ class="w-5 h-5 i-heroicons-solid-chevron-down"
54
+ />
55
+ <div
56
+ v-if="table.sort?.includes('asc')"
57
+ class="w-5 h-5 i-heroicons-solid-chevron-up"
58
+ />
59
+ </span>
60
+ </a>
61
+ </th>
62
+
63
+ <th class="font-semibold text-left text-sm py-3.5 pr-3 pl-4 sm:pl-6 text-gray-900">
64
+ <a
65
+ href="#"
66
+ class="inline-flex group"
67
+ >
68
+ {{ readableLastColumn }}
69
+ <span
70
+ v-if="isColumnSortable(lastColumn[0])"
71
+ :class="isColumnUsedAsSort(lastColumn) ? `bg-gray-200 text-gray-900 group-hover:bg-gray-300` : `text-gray-400 invisible group-hover:visible group-focus:visible`"
72
+ @click="toggleSort(lastColumn[0])"
73
+ >
74
+ <div
75
+ v-if="table.sort?.includes('desc')"
76
+ class="w-5 h-5 i-heroicons-solid-chevron-down"
77
+ />
78
+ <div
79
+ v-if="table.sort?.includes('asc')"
80
+ class="w-5 h-5 i-heroicons-solid-chevron-up"
81
+ />
82
+ </span>
83
+ </a>
84
+ </th>
85
+ </tr>
86
+ </thead>
87
+ </template>
@@ -0,0 +1,146 @@
1
+ <script setup lang="ts">
2
+ const emit = defineEmits(['paginateToNextPage', 'paginateToPreviousPage', 'paginateToPage'])
3
+
4
+ const { goToNextPage, goToPrevPage, goToPage, table, lastPageNumber, totalPages, pages } = await useTable()
5
+
6
+ // watch(totalPages, (newValue, oldValue) => {
7
+ // // eslint-disable-next-line no-console
8
+ // console.log('totalPages', totalPages.value)
9
+
10
+ // // eslint-disable-next-line no-console
11
+ // console.log('oldValue', oldValue)
12
+
13
+ // // eslint-disable-next-line no-console
14
+ // console.log('newValue', newValue)
15
+ // })
16
+
17
+ // const isFirstPage = computed(() => {
18
+ // if (table.currentPage === 1)
19
+ // return true
20
+
21
+ // return false
22
+ // })
23
+
24
+ // const isLastPage = computed(() => {
25
+ // if (table.currentPage === totalPages.value)
26
+ // return true
27
+
28
+ // return false
29
+ // })
30
+
31
+ // console.log('pages', pages.value)
32
+
33
+ function next() {
34
+ goToNextPage()
35
+ emit('paginateToNextPage')
36
+ }
37
+
38
+ function back() {
39
+ goToPrevPage()
40
+ emit('paginateToPreviousPage')
41
+ }
42
+
43
+ function paginateTo(page: number) {
44
+ goToPage(page)
45
+ emit('paginateToPage', page)
46
+ }
47
+
48
+ const currentCount = computed(() => {
49
+ const count = table.perPage * table.currentPage
50
+ const nbHits = table.results?.nbHits || 1
51
+
52
+ return count > nbHits ? table.results?.nbHits : count
53
+ })
54
+ </script>
55
+
56
+ <template>
57
+ <div class="bg-white flex border-gray-200 py-3 items-center justify-end">
58
+ <div class="flex flex-1 justify-between sm:hidden">
59
+ <a
60
+ href="#"
61
+ class="bg-white border rounded-md font-medium border-gray-300 text-sm py-2 px-4 text-gray-700 relative inline-flex items-center hover:bg-gray-50"
62
+ @click.prevent="goToPrevPage()"
63
+ >
64
+ Previous
65
+ </a>
66
+ <a
67
+ href="#"
68
+ class="bg-white border rounded-md font-medium border-gray-300 text-sm ml-3 py-2 px-4 text-gray-700 relative inline-flex items-center hover:bg-gray-50"
69
+ @click.prevent="goToNextPage()"
70
+ >
71
+ Next
72
+ </a>
73
+ </div>
74
+ <div class="min-w-full py-2 hidden inline-block align-middle sm:flex sm:flex-1 sm:items-center sm:justify-between md:px-6 lg:px-8">
75
+ <div>
76
+ <p class="text-sm text-gray-700">
77
+ Showing {{ ((table.perPage * table.currentPage) - table.perPage) + 1 }}
78
+ <span class="font-medium" />
79
+ to
80
+ <span class="font-medium"> {{ currentCount }} </span>
81
+ of
82
+ <span class="font-medium"> {{ table.results?.nbHits ?? 0 }} </span>
83
+ results
84
+ </p>
85
+ </div>
86
+
87
+ <div>
88
+ <nav
89
+ class="-space-x-px rounded-md shadow-sm z-0 relative inline-flex"
90
+ aria-label="Pagination"
91
+ >
92
+ <a
93
+ href="#"
94
+ class="bg-white border rounded-l-md font-medium border-gray-300 text-sm py-2 px-2 text-gray-500 relative inline-flex items-center hover:bg-gray-50"
95
+ @click.prevent="paginateTo(1)"
96
+ >
97
+ <span class="sr-only">First</span>
98
+ <div class="h-4 w-5 i-heroicons-solid-chevron-double-left" />
99
+ </a>
100
+ <a
101
+ href="#"
102
+ class="bg-white border font-medium border-gray-300 text-sm py-2 px-2 text-gray-500 relative inline-flex items-center hover:bg-gray-50"
103
+ @click.prevent="back()"
104
+ >
105
+ <span class="sr-only">Previous</span>
106
+ <div class="h-5 w-5 i-heroicons-solid-chevron-left" />
107
+ </a>
108
+
109
+ <!-- Current: "z-10 bg-indigo-50 border-indigo-500 text-indigo-600", Default: "bg-white border-gray-300 text-gray-500 hover:bg-gray-50" -->
110
+ <a
111
+ v-for="page in pages"
112
+ :key="page"
113
+ href="#"
114
+ aria-current="page"
115
+ :class="[table.currentPage === page && 'border bg-yellow-500 border-yellow-500 text-gray-900 z-10']"
116
+ class="border border-gray-300 text-gray-500 font-medium text-sm py-2 px-4 relative inline-flex items-center underline-transparent"
117
+ @click.prevent="paginateTo(page)"
118
+ >
119
+ {{ page }}
120
+ </a>
121
+ <!-- <a href="#" class="bg-white border font-medium border-gray-300 text-sm py-2 px-4 text-gray-500 relative inline-flex items-center underline-transparent hover:bg-gray-50"> 2 </a>
122
+ <a href="#" class="bg-white border font-medium border-gray-300 text-sm py-2 px-4 text-gray-500 hidden relative items-center underline-transparent md:inline-flex hover:bg-gray-50"> 3 </a>
123
+ <a href="#" class="bg-white border font-medium border-gray-300 text-sm py-2 px-4 text-gray-500 hidden relative items-center underline-transparent md:inline-flex hover:bg-gray-50"> 4 </a>
124
+ <a href="#" class="bg-white border font-medium border-gray-300 text-sm py-2 px-4 text-gray-500 hidden relative items-center underline-transparent md:inline-flex hover:bg-gray-50"> 5 </a> -->
125
+
126
+ <a
127
+ href="#"
128
+ class="bg-white border font-medium border-gray-300 text-sm py-2 px-2 text-gray-500 relative inline-flex items-center underline-transparent hover:bg-gray-50"
129
+ @click.prevent="next()"
130
+ >
131
+ <span class="sr-only">Next</span>
132
+ <div class="h-5 w-5 i-heroicons-solid-chevron-right" />
133
+ </a>
134
+ <a
135
+ href="#"
136
+ class="bg-white border rounded-r-md font-medium border-gray-300 text-sm py-2 px-2 text-gray-500 relative inline-flex items-center underline-transparent hover:bg-gray-50"
137
+ @click.prevent="paginateTo(lastPageNumber)"
138
+ >
139
+ <span class="sr-only">Last</span>
140
+ <div class="h-4 w-5 i-heroicons-solid-chevron-double-right" />
141
+ </a>
142
+ </nav>
143
+ </div>
144
+ </div>
145
+ </div>
146
+ </template>
@@ -0,0 +1,78 @@
1
+ <script setup lang="ts">
2
+ import type { Hit } from '@stacksjs/types'
3
+
4
+ const { hit, index } = defineProps<{ hit: Hit; index: number }>()
5
+
6
+ const { table, columnName } = await useTable()
7
+
8
+ // let's generate the value of the row
9
+ function generateValue(hit: any, col: any) {
10
+ if (col.includes(':'))
11
+ return hit[col.split(':')[0].trim()]
12
+
13
+ return JSON.parse(hit[col])
14
+ }
15
+
16
+ function getClass(index: number) {
17
+ if (index % 2 !== 0)
18
+ return 'bg-gray-200'
19
+
20
+ return 'bg-gray-50'
21
+ }
22
+ </script>
23
+
24
+ <template>
25
+ <tr
26
+ scope="row"
27
+ :class="getClass(index)"
28
+ :data-index="index"
29
+ >
30
+ <td class="relative w-12 px-6 sm:px-8 sm:w-16">
31
+ <div
32
+ v-if="table.selectedRows?.includes(hit.id)"
33
+ class="bg-indigo-600 inset-y-0 left-0 w-0.5 absolute"
34
+ />
35
+ <input
36
+ v-model="table.selectedRows"
37
+ :value="hit.id"
38
+ type="checkbox"
39
+ class="absolute w-4 h-4 -mt-2 text-indigo-600 border-gray-300 rounded top-1/2 left-4 sm:left-6 focus:ring-indigo-500"
40
+ >
41
+ </td>
42
+
43
+ <td
44
+ v-for="(col, x) in table.columns"
45
+ :key="x"
46
+ class="py-4 text-sm font-medium text-gray-900 whitespace-nowrap "
47
+ :class="table.columns.length === x - 1 ? 'table-last-column pr-4 text-right sm:pr-6' : 'pr-3 pl-4 sm:pl-6'"
48
+ >
49
+ <!-- last columns oftentimes are styled slightly different -->
50
+ <!-- <span v-if="(table.columns.length === x + 1) && (table.actionable || table.actions)">
51
+ <slot name="action_column" :row-data="hit">
52
+ <TableCellActionItems />
53
+ </slot>
54
+ </span> -->
55
+
56
+ <span>
57
+ <slot
58
+ :name="columnName(col)"
59
+ :col-data="generateValue(hit, col)"
60
+ >
61
+ {{ generateValue(hit, col) }}
62
+ </slot>
63
+ </span>
64
+ </td>
65
+
66
+ <td v-if="(table.actionable || table.actions)">
67
+ <!-- last columns oftentimes are styled slightly different -->
68
+ <span>
69
+ <slot
70
+ name="action_column"
71
+ :row-data="hit"
72
+ >
73
+ <TableCellActionItems />
74
+ </slot>
75
+ </span>
76
+ </td>
77
+ </tr>
78
+ </template>
@@ -0,0 +1,38 @@
1
+ <script setup lang="ts">
2
+ const { table } = await useTable()
3
+
4
+ const open = ref(false)
5
+ </script>
6
+
7
+ <template>
8
+ <div class="px-8 flex justify-between mx-auto max-w-7xl">
9
+ <div>
10
+ <input
11
+ v-model="table.query"
12
+ type="text"
13
+ class="block w-full shadow-sm focus:ring-indigo-500 p-2 focus:border-indigo-500 sm:max-w-xs sm:text-sm border-gray-300 rounded-md"
14
+ placeholder="type here"
15
+ >
16
+ </div>
17
+
18
+ <div>
19
+ <button
20
+ type="button"
21
+ class="inline-flex items-center px-3 py-2 border border-transparent shadow-sm text-sm leading-4 font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
22
+ @click="open = !open"
23
+ >
24
+ <!-- Heroicon name: solid/mail -->
25
+ <svg
26
+ class="w-4 h-4"
27
+ fill="currentColor"
28
+ viewBox="0 0 20 20"
29
+ xmlns="http://www.w3.org/2000/svg"
30
+ ><path
31
+ fill-rule="evenodd"
32
+ d="M3 3a1 1 0 011-1h12a1 1 0 011 1v3a1 1 0 01-.293.707L12 11.414V15a1 1 0 01-.293.707l-2 2A1 1 0 018 17v-5.586L3.293 6.707A1 1 0 013 6V3z"
33
+ clip-rule="evenodd"
34
+ /></svg>
35
+ </button>
36
+ </div>
37
+ </div>
38
+ </template>
@@ -0,0 +1,10 @@
1
+ <template>
2
+ <el-tooltip
3
+ class="box-item"
4
+ effect="dark"
5
+ content="Top Left prompts info"
6
+ placement="top-start"
7
+ >
8
+ <el-button>top-start</el-button>
9
+ </el-tooltip>
10
+ </template>
@@ -0,0 +1 @@
1
+ export {}
File without changes
@@ -0,0 +1,8 @@
1
+ # Your Functions Library
2
+
3
+ You may use functions to share on npm or have them run on a server behind one of your `../routes`.
4
+
5
+ Learn more about Stacks functions, check out the [documentation](https://stacks.ow3org.com).
6
+
7
+ > **Note**
8
+ > If your project does not require any routes, you can remove this folder._
@@ -0,0 +1,3 @@
1
+ // these APIs are auto-imported from @vueuse/core
2
+ export const isDark = useDark()
3
+ export const toggleDark = useToggle(isDark)
@@ -0,0 +1,2 @@
1
+ export * from './dark'
2
+ export * from './table'
@@ -0,0 +1,180 @@
1
+ import { calculatePagination, currentPage, filterName, filters, goToNextPage, goToPage, goToPrevPage, hits, index, lastPageNumber, perPage, query, results, search, searchFilters, searchParams, setTotalHits, sort, sorts, totalPages } from '@stacksjs/search-engine'
2
+ import { isObject, isString, useStorage } from '@stacksjs/utils'
3
+ import type { Ref, TableStore } from '@stacksjs/types'
4
+ import { computed } from 'vue-demi'
5
+
6
+ const table = (useStorage('table', determineState()).value as TableStore)
7
+
8
+ // table related
9
+ const columns = computed(() => table.columns)
10
+ const actions = computed(() => table.actions)
11
+ const actionable = computed(() => table.actionable)
12
+ const selectedRows = computed(() => table.selectedRows)
13
+ const selectedAll = computed(() => table.selectedAll)
14
+ const pages: Ref<number[]> = ref([])
15
+ const indeterminate = computed(() => (table?.selectedRows?.length ?? 0) > 0 && (table?.selectedRows?.length ?? 0) < hits.value.length)
16
+ const lastColumn = computed(() => {
17
+ return table.columns[table.columns.length - 1]
18
+ })
19
+ const readableLastColumn = computed(() => lastColumn[0]?.includes(':') ? lastColumn[0].split(':')[1].trim() : lastColumn[0])
20
+
21
+ // this watchEffect picks up any reactivity changes from `query` and `searchParams` and it will then trigger a search
22
+ watchEffect(async () => {
23
+ // console.log('watchEffect', query, searchParams)
24
+
25
+ const results = await search(query.value, searchParams.value)
26
+
27
+ if (results) {
28
+ table.results = results
29
+ table.hits = results.hits
30
+ }
31
+
32
+ setTotalHits(table.results?.nbHits ?? 1)
33
+ calculatePagination()
34
+ })
35
+
36
+ watchDebounced(
37
+ query,
38
+ () => {
39
+ // eslint-disable-next-line no-console
40
+ console.log('watchDebounced')
41
+
42
+ if (table === undefined)
43
+ return
44
+
45
+ if (isRef(table.query))
46
+ table.query = query.value
47
+ },
48
+ { debounce: 500 },
49
+ )
50
+
51
+ function determineState(): TableStore {
52
+ const ls = localStorage.getItem('table')
53
+
54
+ if (isString(ls))
55
+ return JSON.parse(ls)
56
+
57
+ // initial default state - overwrite with properties passed down from parent component
58
+ const table: TableStore = {
59
+ source: '',
60
+ password: '',
61
+ index: '',
62
+ columns: [],
63
+ filters: [],
64
+ perPage: 20,
65
+ currentPage: 1,
66
+ query: '',
67
+ }
68
+
69
+ return table
70
+ }
71
+
72
+ function isColumnSortable(col: string): Boolean {
73
+ if (!hasTableLoaded(table))
74
+ return false
75
+
76
+ if (col === undefined)
77
+ return false
78
+
79
+ if (col.includes(':'))
80
+ col = col.split(':')[0]
81
+
82
+ if (table.sorts?.includes(col))
83
+ return true
84
+
85
+ return false
86
+ }
87
+
88
+ function hasTableLoaded(state?: any): Boolean {
89
+ if (state?.index !== '')
90
+ return true
91
+
92
+ return isString(table?.index) && table.index !== '' // a lazy way to check if the table is loaded
93
+ }
94
+
95
+ function isColumnUsedAsSort(col: string | object) {
96
+ let sortKey
97
+
98
+ if (isObject(col))
99
+ sortKey = col[0].includes(':') ? col[0].split(':')[0].trim() : col[0]
100
+
101
+ else
102
+ sortKey = col.includes(':') ? col.split(':')[0].trim() : col
103
+
104
+ return table.sort?.includes(sortKey)
105
+ }
106
+
107
+ function toggleSort(col: string | Ref<string>) {
108
+ if (isRef(col))
109
+ col = unref(col)
110
+
111
+ const sortKey = (col as string).includes(':') ? (col as string).split(':')[0].trim() : col
112
+
113
+ if (table.sort?.includes('desc')) {
114
+ table.sort = `${sortKey}:asc`
115
+
116
+ // eslint-disable-next-line no-console
117
+ console.log('sort included asc it is now desc for', sortKey)
118
+
119
+ return
120
+ }
121
+
122
+ if (table.sort?.includes('asc')) {
123
+ table.sort = undefined
124
+
125
+ // eslint-disable-next-line no-console
126
+ console.log('sort included desc it is now "" for', sortKey)
127
+
128
+ return
129
+ }
130
+
131
+ // eslint-disable-next-line no-console
132
+ console.log('there was no sort. Setting it now in asc order for', sortKey)
133
+
134
+ table.sort = `${sortKey}:desc`
135
+
136
+ // eslint-disable-next-line no-console
137
+ console.log('table.sort', table.sort)
138
+ }
139
+
140
+ function columnName(col: string) {
141
+ return col.split(':')[0].trim()
142
+ }
143
+
144
+ export async function useTable(store?: TableStore) {
145
+ return {
146
+ store,
147
+ table,
148
+ index,
149
+ columns,
150
+ isColumnSortable,
151
+ filters,
152
+ sort,
153
+ sorts,
154
+ query,
155
+ results,
156
+ hits,
157
+ perPage,
158
+ currentPage,
159
+ goToPrevPage,
160
+ goToNextPage,
161
+ goToPage,
162
+ search,
163
+ searchFilters,
164
+ searchParams,
165
+ toggleSort,
166
+ isColumnUsedAsSort,
167
+ actionable,
168
+ actions,
169
+ columnName,
170
+ indeterminate,
171
+ lastColumn,
172
+ readableLastColumn,
173
+ lastPageNumber,
174
+ selectedRows,
175
+ selectedAll,
176
+ totalPages,
177
+ pages,
178
+ filterName,
179
+ }
180
+ }
@@ -0,0 +1,7 @@
1
+ import { assert, describe, test } from 'vitest'
2
+
3
+ describe('example test', () => {
4
+ test('assert', () => {
5
+ assert.equal(1, 1)
6
+ })
7
+ })
@@ -11,7 +11,7 @@ else
11
11
  export NODE_PATH="$NODE_PATH:/home/runner/work/stacks/stacks/node_modules/.pnpm/node_modules"
12
12
  fi
13
13
  if [ -x "$basedir/node" ]; then
14
- exec "$basedir/node" "$basedir/../../../../../node_modules/.pnpm/vitest@0.26.2_@vitest+ui@0.26.2/node_modules/vitest/vitest.mjs" "$@"
14
+ exec "$basedir/node" "$basedir/../../../../../node_modules/.pnpm/vitest@0.26.3_@vitest+ui@0.26.3/node_modules/vitest/vitest.mjs" "$@"
15
15
  else
16
- exec node "$basedir/../../../../../node_modules/.pnpm/vitest@0.26.2_@vitest+ui@0.26.2/node_modules/vitest/vitest.mjs" "$@"
16
+ exec node "$basedir/../../../../../node_modules/.pnpm/vitest@0.26.3_@vitest+ui@0.26.3/node_modules/vitest/vitest.mjs" "$@"
17
17
  fi
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@stacksjs/testing",
3
3
  "type": "module",
4
- "version": "0.47.4",
4
+ "version": "0.48.2",
5
5
  "packageManager": "pnpm@7.21.0",
6
- "description": "The Stacks way to test.",
6
+ "description": "The Stacks way of testing.",
7
7
  "author": "Chris Breuer",
8
8
  "license": "MIT",
9
9
  "funding": "https://github.com/sponsors/chrisbbreuer",
@@ -18,11 +18,14 @@
18
18
  },
19
19
  "keywords": [
20
20
  "tests",
21
- "e2e",
22
21
  "unit",
22
+ "feature",
23
+ "e2e",
23
24
  "testing",
24
25
  "utilities",
25
26
  "functions",
27
+ "playwright",
28
+ "vitest",
26
29
  "stacks"
27
30
  ],
28
31
  "main": "dist/index.mjs",
@@ -47,9 +50,9 @@
47
50
  },
48
51
  "peerDependencies": {
49
52
  "@playwright/test": "^1.29.1",
50
- "@vitest/coverage-istanbul": "^0.26.2",
51
- "@vitest/ui": "^0.26.2",
52
- "vitest": "^0.26.2"
53
+ "@vitest/coverage-istanbul": "^0.26.3",
54
+ "@vitest/ui": "^0.26.3",
55
+ "vitest": "^0.26.3"
53
56
  },
54
57
  "devDependencies": {
55
58
  "mkdist": "^1.0.0",
@@ -11,7 +11,7 @@ else
11
11
  export NODE_PATH="$NODE_PATH:/home/runner/work/stacks/stacks/node_modules/.pnpm/node_modules"
12
12
  fi
13
13
  if [ -x "$basedir/node" ]; then
14
- exec "$basedir/node" "$basedir/../../../../../node_modules/.pnpm/vitepress@1.0.0-alpha.33_j73j5xdbzpkigstapj6vkce2xy/node_modules/vitepress/bin/vitepress.js" "$@"
14
+ exec "$basedir/node" "$basedir/../../../../../node_modules/.pnpm/vitepress@1.0.0-alpha.34_j73j5xdbzpkigstapj6vkce2xy/node_modules/vitepress/bin/vitepress.js" "$@"
15
15
  else
16
- exec node "$basedir/../../../../../node_modules/.pnpm/vitepress@1.0.0-alpha.33_j73j5xdbzpkigstapj6vkce2xy/node_modules/vitepress/bin/vitepress.js" "$@"
16
+ exec node "$basedir/../../../../../node_modules/.pnpm/vitepress@1.0.0-alpha.34_j73j5xdbzpkigstapj6vkce2xy/node_modules/vitepress/bin/vitepress.js" "$@"
17
17
  fi
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@stacksjs/types",
3
3
  "type": "module",
4
- "version": "0.47.4",
4
+ "version": "0.48.2",
5
5
  "packageManager": "pnpm@7.21.0",
6
6
  "description": "The Stacks framework types.",
7
7
  "author": "Chris Breuer",
@@ -46,6 +46,7 @@
46
46
  "@mdit-vue/plugin-component": "^0.11.2",
47
47
  "@mdit-vue/plugin-frontmatter": "^0.11.1",
48
48
  "@mdit-vue/types": "^0.11.0",
49
+ "@prisma/client": "^4.8.0",
49
50
  "@rollup/pluginutils": "^5.0.2",
50
51
  "@types/bcryptjs": "^2.4.2",
51
52
  "@types/crypto-js": "^4.1.1",
@@ -63,9 +64,9 @@
63
64
  "typescript": "^4.9.4",
64
65
  "unplugin-auto-import": "^0.12.1",
65
66
  "unplugin-vue-components": "^0.22.12",
66
- "vite-plugin-inspect": "^0.7.11",
67
+ "vite-plugin-inspect": "^0.7.12",
67
68
  "vite-plugin-vue-layouts": "^0.7.0",
68
69
  "vite-ssg": "^0.22.1",
69
- "vitepress": "1.0.0-alpha.33"
70
+ "vitepress": "1.0.0-alpha.34"
70
71
  }
71
72
  }