adminforth 1.0.51 → 1.0.52

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.
@@ -72,7 +72,7 @@ class CodeInjector {
72
72
  }
73
73
  prepareSources(_a) {
74
74
  return __awaiter(this, arguments, void 0, function* ({ filesUpdated, verbose = false }) {
75
- var _b, _c, _d, _e, _f, _g, _h;
75
+ var _b, _c, _d, _e, _f, _g, _h, _j, _k;
76
76
  // check SPA_TMP_PATH exists and create if not
77
77
  try {
78
78
  yield fs.promises.access(CodeInjector.SPA_TMP_PATH, fs.constants.F_OK);
@@ -213,13 +213,22 @@ class CodeInjector {
213
213
  appVueContent = appVueContent.replace('/* IMPORTANT:ADMINFORTH CUSTOM USES */', 'addCustomUses(app);');
214
214
  }
215
215
  yield fs.promises.writeFile(appVuePath, appVueContent);
216
+ // generate tailwind extend styles
217
+ if ((_f = this.adminforth.config) === null || _f === void 0 ? void 0 : _f.styles) {
218
+ const tailwindStyles = (_g = this.adminforth.config) === null || _g === void 0 ? void 0 : _g.styles;
219
+ const stylesText = JSON.stringify(tailwindStyles, null, 2).slice(1, -1);
220
+ let tailwindConfigPath = path.join(CodeInjector.SPA_TMP_PATH, 'tailwind.config.js');
221
+ let tailwindConfigContent = yield fs.promises.readFile(tailwindConfigPath, 'utf-8');
222
+ tailwindConfigContent = tailwindConfigContent.replace('/* IMPORTANT:ADMINFORTH TAILWIND STYLES */', stylesText);
223
+ yield fs.promises.writeFile(tailwindConfigPath, tailwindConfigContent);
224
+ }
216
225
  /* generate custom rotes */
217
226
  const homepageMenuItem = this.adminforth.config.menu.find((mi) => mi.homepage);
218
227
  let childrenHomePageMenuItem = this.adminforth.config.menu.find((mi) => { var _a; return mi.children && ((_a = mi.children) === null || _a === void 0 ? void 0 : _a.find((mi) => mi.homepage)); });
219
- let childrenHomepage = (_f = childrenHomePageMenuItem === null || childrenHomePageMenuItem === void 0 ? void 0 : childrenHomePageMenuItem.children) === null || _f === void 0 ? void 0 : _f.find((mi) => mi.homepage);
228
+ let childrenHomepage = (_h = childrenHomePageMenuItem === null || childrenHomePageMenuItem === void 0 ? void 0 : childrenHomePageMenuItem.children) === null || _h === void 0 ? void 0 : _h.find((mi) => mi.homepage);
220
229
  let homePagePath = (homepageMenuItem === null || homepageMenuItem === void 0 ? void 0 : homepageMenuItem.path) || `/resource/${childrenHomepage === null || childrenHomepage === void 0 ? void 0 : childrenHomepage.resourceId}`;
221
230
  if (!homePagePath) {
222
- homePagePath = ((_g = this.adminforth.config.menu.filter((mi) => mi.path)[0]) === null || _g === void 0 ? void 0 : _g.path) || `/resource/${(_h = this.adminforth.config.menu.filter((mi) => mi.children)[0]) === null || _h === void 0 ? void 0 : _h.resourceId}`;
231
+ homePagePath = ((_j = this.adminforth.config.menu.filter((mi) => mi.path)[0]) === null || _j === void 0 ? void 0 : _j.path) || `/resource/${(_k = this.adminforth.config.menu.filter((mi) => mi.children)[0]) === null || _k === void 0 ? void 0 : _k.resourceId}`;
223
232
  }
224
233
  routes += `{
225
234
  path: '/',
@@ -16,8 +16,8 @@
16
16
  </script> -->
17
17
 
18
18
  </head>
19
- <body>
20
- <div id="app" class="min-h-screen dark:bg-gray-800"></div>
19
+ <body class=" ">
20
+ <div id="app" class="min-h-screen bg-html-bg dark:bg-gray-800"></div>
21
21
  <script type="module" src="/src/main.ts"></script>
22
22
  </body>
23
23
  </html>
@@ -9,6 +9,7 @@
9
9
  "version": "0.0.0",
10
10
  "dependencies": {
11
11
  "@iconify-prerendered/vue-flowbite": "^0.23.1714023977",
12
+ "@unhead/vue": "^1.9.12",
12
13
  "@vueuse/core": "^10.10.0",
13
14
  "dayjs": "^1.11.11",
14
15
  "debounce": "^2.1.0",
@@ -1185,6 +1186,23 @@
1185
1186
  "url": "https://github.com/sponsors/harlan-zw"
1186
1187
  }
1187
1188
  },
1189
+ "node_modules/@unhead/vue": {
1190
+ "version": "1.9.12",
1191
+ "resolved": "https://registry.npmjs.org/@unhead/vue/-/vue-1.9.12.tgz",
1192
+ "integrity": "sha512-keE4EuswgzCqVU7zmZprU+ToMvNWc3s8NoLreH5AtJd2u0FgBygD8sxRVyEnZw1KwFYOJ2C7yD2TChSKZioPGQ==",
1193
+ "dependencies": {
1194
+ "@unhead/schema": "1.9.12",
1195
+ "@unhead/shared": "1.9.12",
1196
+ "hookable": "^5.5.3",
1197
+ "unhead": "1.9.12"
1198
+ },
1199
+ "funding": {
1200
+ "url": "https://github.com/sponsors/harlan-zw"
1201
+ },
1202
+ "peerDependencies": {
1203
+ "vue": ">=2.7 || >=3"
1204
+ }
1205
+ },
1188
1206
  "node_modules/@vitejs/plugin-vue": {
1189
1207
  "version": "5.0.4",
1190
1208
  "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.0.4.tgz",
@@ -13,6 +13,7 @@
13
13
  },
14
14
  "dependencies": {
15
15
  "@iconify-prerendered/vue-flowbite": "^0.23.1714023977",
16
+ "@unhead/vue": "^1.9.12",
16
17
  "@vueuse/core": "^10.10.0",
17
18
  "dayjs": "^1.11.11",
18
19
  "debounce": "^2.1.0",
@@ -1,89 +1,84 @@
1
1
  <template>
2
2
  <nav
3
3
  v-if="loggedIn"
4
-
5
- class="fixed h-14 top-0 z-50 w-full bg-white border-b border-gray-200 dark:bg-gray-800 dark:border-gray-700">
4
+ class="fixed h-14 top-0 z-40 w-full border-b shadow-sm bg-header-bg shadow-header-shadow dark:bg-header-bg-hover dark:border-nav-menu-devider">
6
5
  <div class="px-3 py-3 lg:px-5 lg:pl-3">
7
6
  <div class="flex items-center justify-between">
8
7
  <div class="flex items-center justify-start rtl:justify-end">
9
- <button data-drawer-target="logo-sidebar" data-drawer-toggle="logo-sidebar" aria-controls="logo-sidebar" type="button" class="inline-flex items-center p-2 text-sm text-gray-500 rounded-lg sm:hidden hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200 dark:text-gray-400 dark:hover:bg-gray-700 dark:focus:ring-gray-600">
8
+ <button data-drawer-target="logo-sidebar" data-drawer-toggle="logo-sidebar" aria-controls="logo-sidebar" type="button" class="inline-flex items-center p-2 text-sm rounded-lg sm:hidden hover:bg-nav-menu-bg-hover focus:outline-none focus:ring-2 focus:ring-nav-menu-devider dark:text-nav-menu-icons dark:hover:bg-nav-menu-bg-hover dark:focus:ring-nav-menu-devider">
10
9
  <span class="sr-only">Open sidebar</span>
11
10
  <svg class="w-6 h-6" aria-hidden="true" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
12
11
  <path clip-rule="evenodd" fill-rule="evenodd" d="M2 4.75A.75.75 0 012.75 4h14.5a.75.75 0 010 1.5H2.75A.75.75 0 012 4.75zm0 10.5a.75.75 0 01.75-.75h7.5a.75.75 0 010 1.5h-7.5a.75.75 0 01-.75-.75zM2 10a.75.75 0 01.75-.75h14.5a.75.75 0 010 1.5H2.75A.75.75 0 012 10z"></path>
13
12
  </svg>
14
13
  </button>
15
- <div class="flex ms-2 md:me-24">
16
- <img src="https://flowbite.com/docs/images/logo.svg" class="h-8 me-3" alt="FlowBite Logo" />
17
- <span class="self-center text-xl font-semibold sm:text-2xl whitespace-nowrap dark:text-white">
18
- {{ coreStore.config?.brandName }}
19
- </span>
20
- </div>
14
+
21
15
  </div>
22
16
  <div class="flex items-center">
23
-
24
-
25
- <div class="flex items-center ms-3">
26
- <div>
27
- <button type="button" class="flex text-sm bg-gray-100 rounded-full focus:ring-4 focus:ring-gray-300 dark:focus:ring-gray-600 dark:bg-gray-700" aria-expanded="false" data-dropdown-toggle="dropdown-user">
28
- <span class="sr-only">Open user menu</span>
29
- <svg class="w-8 h-8 text-gray-400 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 24 24">
30
- <path fill-rule="evenodd" d="M12 20a7.966 7.966 0 0 1-5.002-1.756l.002.001v-.683c0-1.794 1.492-3.25 3.333-3.25h3.334c1.84 0 3.333 1.456 3.333 3.25v.683A7.966 7.966 0 0 1 12 20ZM2 12C2 6.477 6.477 2 12 2s10 4.477 10 10c0 5.5-4.44 9.963-9.932 10h-.138C6.438 21.962 2 17.5 2 12Zm10-5c-1.84 0-3.333 1.455-3.333 3.25S10.159 13.5 12 13.5c1.84 0 3.333-1.455 3.333-3.25S13.841 7 12 7Z" clip-rule="evenodd"/>
31
- </svg>
32
-
33
- </button>
17
+ <div class="flex items-center ms-3 ">
18
+ <div>
19
+ <button type="button" class="flex text-sm bg-header-bg-hover rounded-full focus:ring-4 focus:ring-nav-menu-devider dark:focus:ring-nav-menu-devider dark:bg-header-bg-hover" aria-expanded="false" data-dropdown-toggle="dropdown-user">
20
+ <span class="sr-only">Open user menu</span>
21
+ <svg class="w-8 h-8 text-nav-menu-icons dark:text-header-icons" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 24 24">
22
+ <path fill-rule="evenodd" d="M12 20a7.966 7.966 0 0 1-5.002-1.756l.002.001v-.683c0-1.794 1.492-3.25 3.333-3.25h3.334c1.84 0 3.333 1.456 3.333 3.25v.683A7.966 7.966 0 0 1 12 20ZM2 12C2 6.477 6.477 2 12 2s10 4.477 10 10c0 5.5-4.44 9.963-9.932 10h-.138C6.438 21.962 2 17.5 2 12Zm10-5c-1.84 0-3.333 1.455-3.333 3.25S10.159 13.5 12 13.5c1.84 0 3.333-1.455 3.333-3.25S13.841 7 12 7Z" clip-rule="evenodd"/>
23
+ </svg>
24
+ </button>
25
+ </div>
26
+ <div class="z-50 hidden my-4 text-base list-none bg-white divide-y divide-gray-100 rounded shadow dark:shadow-black dark:bg-nav-menu-bg dark:divide-nav-menu-devider dark:shadow-black" id="dropdown-user">
27
+ <div class="px-4 py-3" role="none">
28
+ <p class="text-sm text-gray-900 dark:text-header-text" role="none" v-if="coreStore.userFullname">
29
+ {{ coreStore.userFullname }}
30
+ </p>
31
+ <p class="text-sm font-medium text-gray-900 truncate dark:text-nav-menu-text" role="none">
32
+ {{ coreStore.username }}
33
+ </p>
34
34
  </div>
35
- <div class="z-50 hidden my-4 text-base list-none bg-white divide-y divide-gray-100 rounded shadow dark:shadow-black dark:bg-gray-700 dark:divide-gray-600 dark:shadow-black" id="dropdown-user">
36
- <div class="px-4 py-3" role="none">
37
- <p class="text-sm text-gray-900 dark:text-white" role="none" v-if="coreStore.userFullname">
38
- {{ coreStore.userFullname }}
39
- </p>
40
- <p class="text-sm font-medium text-gray-900 truncate dark:text-gray-300" role="none">
41
- {{ coreStore.username }}
42
- </p>
43
- </div>
44
- <ul class="py-1" role="none">
45
- <li >
46
- <span @click="toggleTheme" class=" cursor-pointer flex items-center gap-1 block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-600 dark:hover:text-white" role="menuitem">
47
- {{ theme === 'dark' ? 'Light' : 'Dark' }}
48
- <IconMoonSolid class="w-5 h-5 text-blue-300
49
- " v-if="theme !== 'dark'"/>
50
- <IconSunSolid class="w-5 h-5 text-yellow-300
51
- " v-else/>
52
- mode
53
- </span>
54
- </li>
55
-
56
- <li>
57
- <button @click="logout" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-600 dark:hover:text-white" role="menuitem">Sign out</button>
35
+ <ul class="py-1" role="none">
36
+ <li>
37
+ <span @click="toggleTheme" class="cursor-pointer flex items-center gap-1 block px-4 py-2 text-sm text-black hover:bg-html-bg dark:text-nav-menu-text-hover dark:hover:bg-nav-menu-hover dark:hover:text-nav-menu-text-active" role="menuitem">
38
+ {{ theme === 'dark' ? 'Light' : 'Dark' }}
39
+ <IconMoonSolid class="w-5 h-5 text-blue-300" v-if="theme !== 'dark'" />
40
+ <IconSunSolid class="w-5 h-5 text-yellow-300" v-else />
41
+ mode
42
+ </span>
58
43
  </li>
59
- </ul>
60
- </div>
44
+ <li>
45
+ <button @click="logout" class="cursor-pointer flex items-center gap-1 block px-4 py-2 text-sm text-black hover:bg-html-bg dark:text-nav-menu-text-hover dark:hover:bg-nav-menu-hover dark:hover:text-nav-menu-text-active w-full" role="menuitem">Sign out</button>
46
+ </li>
47
+ </ul>
61
48
  </div>
62
49
  </div>
50
+ </div>
63
51
  </div>
64
52
  </div>
65
- </nav>
53
+ </nav>
54
+
66
55
 
67
56
 
68
57
  <aside
69
58
  v-if="loggedIn"
70
59
 
71
- id="logo-sidebar" class="fixed top-0 left-0 z-10 w-64 h-screen pt-20 transition-transform -translate-x-full bg-white border-r border-gray-200 sm:translate-x-0 dark:bg-gray-800 dark:border-gray-700" aria-label="Sidebar">
72
- <div class="h-full px-3 pb-4 overflow-y-auto bg-white dark:bg-gray-800">
60
+ id="logo-sidebar" class="fixed border-none top-0 left-0 z-50 w-64 h-screen transition-transform -translate-x-full bg-nav-menu-bg border-r border- sm:translate-x-0 dark:bg-gray-800 dark:border-gray-700" aria-label="Sidebar">
61
+ <div class="h-full px-3 pb-4 overflow-y-auto bg-nav-menu-bg dark:bg-gray-800">
62
+ <div class="flex ms-2 md:me-24 m-4 ">
63
+ <img src="https://flowbite.com/docs/images/logo.svg" class="h-8 me-3" alt="FlowBite Logo" />
64
+ <span class="self-center text-xl font-semibold sm:text-2xl whitespace-nowrap dark:text-header-text text-header-logo-color">
65
+ {{ coreStore.config?.brandName }}
66
+ </span>
67
+ </div>
73
68
  <ul class="space-y-2 font-medium">
74
69
  <template v-for="(item, i) in coreStore.menu" :key="`menu-${i}`">
75
- <div v-if="item.type === 'divider'" class="border-t border-gray-200 dark:border-gray-700"></div>
70
+ <div v-if="item.type === 'divider'" class="border-t border-nav-menu-devider dark:border-gray-700"></div>
76
71
  <div v-else-if="item.type === 'gap'" class="flex items-center justify-center h-8"></div>
77
72
  <div v-else-if="item.type === 'heading'" class="flex items-center justify-left pl-2 h-8 text-gray-400 dark:text-gray-400
78
73
  ">{{ item.label }}</div>
79
74
 
80
75
 
81
76
  <li v-else-if="item.children">
82
- <button type="button" class="flex items-center w-full p-2 text-base text-gray-900 transition duration-75 rounded-lg group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700"
77
+ <button type="button" class="flex items-center w-full p-2 text-base text-nav-menu-text transition duration-75 group hover:bg-nav-menu-bg-hover dark:text-white dark:hover:bg-gray-700"
83
78
  :aria-controls="`dropdown-example${i}`"
84
79
  :data-collapse-toggle="`dropdown-example${i}`"
85
80
  >
86
- <component v-if="item.icon" :is="getIcon(item.icon)" class="w-5 h-5 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white" ></component>
81
+ <component v-if="item.icon" :is="getIcon(item.icon)" class="w-5 h-5 text-gray-500 transition duration-75 dark:text-gray-400 dark:group-hover:text-white" ></component>
87
82
 
88
83
  <span class="flex-1 ms-3 text-left rtl:text-right whitespace-nowrap">{{ item.label }}</span>
89
84
  <svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 10 6">
@@ -135,6 +130,7 @@ import { useRoute, useRouter } from 'vue-router';
135
130
  import { getIcon } from '@/utils';
136
131
  import { useHead } from 'unhead'
137
132
  import { createHead } from 'unhead'
133
+ // import { link } from 'fs';
138
134
  const coreStore = useCoreStore();
139
135
 
140
136
 
@@ -182,6 +178,12 @@ onMounted(async () => {
182
178
  title.value = coreStore.config.title || 'Admin Forth';
183
179
  useHead({
184
180
  title: title.value,
181
+ link: [
182
+ {
183
+ rel: 'icon',
184
+ href: coreStore.config.favicon || '/favicon.ico',
185
+ },
186
+ ],
185
187
 
186
188
  })
187
189
  })
@@ -9,7 +9,8 @@
9
9
  :placeholder="selectedItems.length ? '' : 'Select...'"
10
10
  />
11
11
  <div class="absolute inset-y-0 left-2 flex items-center pr-2 flex-wrap">
12
- <div v-for="item in selectedItems" :key="item.name" class="bg-blue-100 text-blue-800 text-xs font-medium me-2 px-2.5 py-0.5 rounded dark:bg-blue-900 dark:text-blue-300">
12
+ {{ }}
13
+ <div v-for="item in selectedItems" :key="item?.name" class="bg-blue-100 text-blue-800 text-xs font-medium me-2 px-2.5 py-0.5 rounded dark:bg-blue-900 dark:text-blue-300">
13
14
  <span>{{ item.label }}</span>
14
15
  <button
15
16
  type="button"
@@ -1,11 +1,11 @@
1
1
  <template>
2
2
  <RouterLink
3
3
  :to="{name: item.resourceId ? 'resource-list' : item.path, params: item.resourceId ? { resourceId: item.resourceId }: {}}"
4
- class="flex items-center py-2 text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-600 dark:hover:text-white" role="menuitem"
4
+ class="flex items-center py-2 text-nav-menu-text hover:bg-nav-menu-bg-hover active:bg-nav-menu-bg-active" role="menuitem"
5
5
  :class="{
6
6
  'px-4': isChild,
7
7
  'px-2': !isChild,
8
- 'bg-blue-100 dark:bg-gray-700': item.resourceId ?
8
+ 'bg-nav-menu-bg-active dark:bg-gray-700': item.resourceId ?
9
9
  ($route.params.resourceId === item.resourceId && $route.name === 'resource-list') :
10
10
  ($route.name === item.path)
11
11
  }"
@@ -2,11 +2,11 @@
2
2
  <div>
3
3
 
4
4
  <div
5
- class="relative shadow-md sm:rounded-lg dark:shadow-2xl dark:shadow-black"
5
+ class="relative shadow-resourse-form-shadow sm:rounded-lg dark:shadow-2xl dark:shadow-black"
6
6
  >
7
7
  <form autocomplete="off" @submit.prevent>
8
8
  <table class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
9
- <thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
9
+ <thead class="text-xs text-gray-700 uppercase bg-form-view-heading dark:bg-gray-700 dark:text-gray-400">
10
10
  <tr>
11
11
  <th scope="col" class="px-6 py-3">
12
12
  Field
@@ -18,7 +18,7 @@
18
18
  </thead>
19
19
  <tbody>
20
20
  <tr v-for="column, i in editableColumns" :key="column.name"
21
- class="odd:bg-white odd:dark:bg-gray-900 even:bg-gray-50 even:dark:bg-gray-800 border-b dark:border-gray-700"
21
+ class="bg-form-view-bg dark:bg-gray-800 border-b dark:border-gray-700"
22
22
  >
23
23
  <!-- if column is in customComponentsPerColumn, use this component. If not, use this code -->
24
24
  <template v-if="customComponentsPerColumn[column.name]">
@@ -65,7 +65,7 @@
65
65
  </BreadcrumbsWithButtons>
66
66
 
67
67
  <!-- table -->
68
- <div class="relative overflow-x-auto shadow-md dark:shadow-black sm:rounded-lg dark:s">
68
+ <div class="relative overflow-x-auto shadow-list-table-shadow dark:shadow-black dark:s">
69
69
 
70
70
 
71
71
  <!-- skelet loader -->
@@ -90,7 +90,7 @@
90
90
  </div>
91
91
 
92
92
  <table v-else class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
93
- <thead class="text-xs text-gray-700 bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
93
+ <thead class="text-xs text-view-table-heading-text bg-list-view-table-heading dark:bg-gray-700 dark:text-gray-400">
94
94
  <tr>
95
95
  <th scope="col" class="p-4">
96
96
  <div v-if="rows && rows.length" class="flex items-center">
@@ -127,7 +127,7 @@
127
127
  </tr>
128
128
  </thead>
129
129
  <tbody>
130
- <tr v-if="!rows" class="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
130
+ <tr v-if="!rows" class="bg-list-view-table-bg border-b dark:bg-gray-800 dark:border-gray-700">
131
131
  <td :colspan="coreStore.resourceColumns.length + 2">
132
132
 
133
133
  <div role="status"
@@ -171,7 +171,7 @@
171
171
  </div>
172
172
  </td>
173
173
  </tr>
174
- <tr v-else-if="rows.length === 0" class="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
174
+ <tr v-else-if="rows.length === 0" class="bg-list-view-table-bg border-b dark:bg-gray-800 dark:border-gray-700">
175
175
  <td :colspan="coreStore.resourceColumns.length + 2">
176
176
 
177
177
  <div id="toast-simple"
@@ -185,7 +185,7 @@
185
185
  </tr>
186
186
 
187
187
  <tr v-else v-for="(row, rowI) in rows" :key="row.id"
188
- class="bg-white border-b dark:bg-gray-800 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600">
188
+ class="bg-list-view-table-bg border-b dark:bg-gray-800 border-list-view-border-color dark:border-gray-700 hover:bg-list-view-table-row-hover dark:hover:bg-gray-600">
189
189
  <td class="w-4 p-4">
190
190
  <div class="flex items center">
191
191
  <input
@@ -27,10 +27,10 @@
27
27
  </div>
28
28
  <div
29
29
  v-else
30
- class="relative overflow-x-auto shadow-md sm:rounded-lg"
30
+ class="relative overflow-x-auto shadow-resourse-form-shadow "
31
31
  >
32
32
  <table class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
33
- <thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
33
+ <thead class="text-xs text-gray-700 uppercase bg-form-view-heading dark:bg-gray-700 dark:text-gray-400">
34
34
  <tr>
35
35
  <th scope="col" class="px-6 py-3">
36
36
  Field
@@ -42,7 +42,7 @@
42
42
  </thead>
43
43
  <tbody>
44
44
  <tr v-for="column in coreStore.resourceColumns?.filter(c => c.showIn.includes('show'))" :key="column.name"
45
- class="odd:bg-white odd:dark:bg-gray-900 even:bg-gray-50 even:dark:bg-gray-800 border-b dark:border-gray-700"
45
+ class="bg-form-view-bg odd:dark:bg-gray-900 even:dark:bg-gray-800 border-b dark:border-gray-700"
46
46
  >
47
47
  <td class="px-6 py-4 whitespace-nowrap">
48
48
  {{ column.label }}
@@ -1,9 +1,12 @@
1
1
  /** @type {import('tailwindcss').Config} */
2
2
  export default {
3
- content: ["./src/**/*.{vue, js}", "./node_modules/flowbite/**/*.js"],
3
+ content: ["./src/**/*.{vue, js}","./src/*.{vue, js}", "./index.html", "./node_modules/flowbite/**/*.js"],
4
4
  theme: {
5
- extend: {},
5
+ extend: {
6
+ /* IMPORTANT:ADMINFORTH TAILWIND STYLES */
7
+ }
6
8
  },
9
+
7
10
  darkMode: 'class',
8
11
  plugins: [
9
12
  require('flowbite/plugin'),
package/index.ts CHANGED
@@ -16,6 +16,11 @@ const AVAILABLE_SHOW_IN = ['list', 'edit', 'create', 'filter', 'show'];
16
16
  const DEFAULT_ALLOWED_ACTIONS = {create: true, edit: true, show: true, delete: true};
17
17
 
18
18
 
19
+ type ValidationObject = {
20
+ regex: string,
21
+ message: string,
22
+ }
23
+
19
24
  class AdminForth {
20
25
  static Types = AdminForthTypes;
21
26
 
@@ -239,6 +239,17 @@ class CodeInjector {
239
239
  }
240
240
  await fs.promises.writeFile(appVuePath, appVueContent);
241
241
 
242
+ // generate tailwind extend styles
243
+ if(this.adminforth.config?.styles){
244
+ const tailwindStyles = this.adminforth.config?.styles
245
+ const stylesText = JSON.stringify(tailwindStyles, null, 2).slice(1, -1);
246
+ let tailwindConfigPath = path.join(CodeInjector.SPA_TMP_PATH, 'tailwind.config.js');
247
+ let tailwindConfigContent = await fs.promises.readFile(tailwindConfigPath, 'utf-8');
248
+ tailwindConfigContent = tailwindConfigContent.replace('/* IMPORTANT:ADMINFORTH TAILWIND STYLES */', stylesText);
249
+ await fs.promises.writeFile(tailwindConfigPath, tailwindConfigContent);
250
+ }
251
+
252
+
242
253
 
243
254
  /* generate custom rotes */
244
255
  const homepageMenuItem = this.adminforth.config.menu.find((mi)=>mi.homepage);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adminforth",
3
- "version": "1.0.51",
3
+ "version": "1.0.52",
4
4
  "description": "OpenSource Vue3 powered forth-generation admin panel",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/spa/index.html CHANGED
@@ -16,8 +16,8 @@
16
16
  </script> -->
17
17
 
18
18
  </head>
19
- <body>
20
- <div id="app" class="min-h-screen dark:bg-gray-800"></div>
19
+ <body class=" ">
20
+ <div id="app" class="min-h-screen bg-html-bg dark:bg-gray-800"></div>
21
21
  <script type="module" src="/src/main.ts"></script>
22
22
  </body>
23
23
  </html>
@@ -9,6 +9,7 @@
9
9
  "version": "0.0.0",
10
10
  "dependencies": {
11
11
  "@iconify-prerendered/vue-flowbite": "^0.23.1714023977",
12
+ "@unhead/vue": "^1.9.12",
12
13
  "@vueuse/core": "^10.10.0",
13
14
  "dayjs": "^1.11.11",
14
15
  "debounce": "^2.1.0",
@@ -1185,6 +1186,23 @@
1185
1186
  "url": "https://github.com/sponsors/harlan-zw"
1186
1187
  }
1187
1188
  },
1189
+ "node_modules/@unhead/vue": {
1190
+ "version": "1.9.12",
1191
+ "resolved": "https://registry.npmjs.org/@unhead/vue/-/vue-1.9.12.tgz",
1192
+ "integrity": "sha512-keE4EuswgzCqVU7zmZprU+ToMvNWc3s8NoLreH5AtJd2u0FgBygD8sxRVyEnZw1KwFYOJ2C7yD2TChSKZioPGQ==",
1193
+ "dependencies": {
1194
+ "@unhead/schema": "1.9.12",
1195
+ "@unhead/shared": "1.9.12",
1196
+ "hookable": "^5.5.3",
1197
+ "unhead": "1.9.12"
1198
+ },
1199
+ "funding": {
1200
+ "url": "https://github.com/sponsors/harlan-zw"
1201
+ },
1202
+ "peerDependencies": {
1203
+ "vue": ">=2.7 || >=3"
1204
+ }
1205
+ },
1188
1206
  "node_modules/@vitejs/plugin-vue": {
1189
1207
  "version": "5.0.4",
1190
1208
  "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.0.4.tgz",
package/spa/package.json CHANGED
@@ -13,6 +13,7 @@
13
13
  },
14
14
  "dependencies": {
15
15
  "@iconify-prerendered/vue-flowbite": "^0.23.1714023977",
16
+ "@unhead/vue": "^1.9.12",
16
17
  "@vueuse/core": "^10.10.0",
17
18
  "dayjs": "^1.11.11",
18
19
  "debounce": "^2.1.0",
package/spa/src/App.vue CHANGED
@@ -1,89 +1,84 @@
1
1
  <template>
2
2
  <nav
3
3
  v-if="loggedIn"
4
-
5
- class="fixed h-14 top-0 z-50 w-full bg-white border-b border-gray-200 dark:bg-gray-800 dark:border-gray-700">
4
+ class="fixed h-14 top-0 z-40 w-full border-b shadow-sm bg-header-bg shadow-header-shadow dark:bg-header-bg-hover dark:border-nav-menu-devider">
6
5
  <div class="px-3 py-3 lg:px-5 lg:pl-3">
7
6
  <div class="flex items-center justify-between">
8
7
  <div class="flex items-center justify-start rtl:justify-end">
9
- <button data-drawer-target="logo-sidebar" data-drawer-toggle="logo-sidebar" aria-controls="logo-sidebar" type="button" class="inline-flex items-center p-2 text-sm text-gray-500 rounded-lg sm:hidden hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200 dark:text-gray-400 dark:hover:bg-gray-700 dark:focus:ring-gray-600">
8
+ <button data-drawer-target="logo-sidebar" data-drawer-toggle="logo-sidebar" aria-controls="logo-sidebar" type="button" class="inline-flex items-center p-2 text-sm rounded-lg sm:hidden hover:bg-nav-menu-bg-hover focus:outline-none focus:ring-2 focus:ring-nav-menu-devider dark:text-nav-menu-icons dark:hover:bg-nav-menu-bg-hover dark:focus:ring-nav-menu-devider">
10
9
  <span class="sr-only">Open sidebar</span>
11
10
  <svg class="w-6 h-6" aria-hidden="true" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
12
11
  <path clip-rule="evenodd" fill-rule="evenodd" d="M2 4.75A.75.75 0 012.75 4h14.5a.75.75 0 010 1.5H2.75A.75.75 0 012 4.75zm0 10.5a.75.75 0 01.75-.75h7.5a.75.75 0 010 1.5h-7.5a.75.75 0 01-.75-.75zM2 10a.75.75 0 01.75-.75h14.5a.75.75 0 010 1.5H2.75A.75.75 0 012 10z"></path>
13
12
  </svg>
14
13
  </button>
15
- <div class="flex ms-2 md:me-24">
16
- <img src="https://flowbite.com/docs/images/logo.svg" class="h-8 me-3" alt="FlowBite Logo" />
17
- <span class="self-center text-xl font-semibold sm:text-2xl whitespace-nowrap dark:text-white">
18
- {{ coreStore.config?.brandName }}
19
- </span>
20
- </div>
14
+
21
15
  </div>
22
16
  <div class="flex items-center">
23
-
24
-
25
- <div class="flex items-center ms-3">
26
- <div>
27
- <button type="button" class="flex text-sm bg-gray-100 rounded-full focus:ring-4 focus:ring-gray-300 dark:focus:ring-gray-600 dark:bg-gray-700" aria-expanded="false" data-dropdown-toggle="dropdown-user">
28
- <span class="sr-only">Open user menu</span>
29
- <svg class="w-8 h-8 text-gray-400 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 24 24">
30
- <path fill-rule="evenodd" d="M12 20a7.966 7.966 0 0 1-5.002-1.756l.002.001v-.683c0-1.794 1.492-3.25 3.333-3.25h3.334c1.84 0 3.333 1.456 3.333 3.25v.683A7.966 7.966 0 0 1 12 20ZM2 12C2 6.477 6.477 2 12 2s10 4.477 10 10c0 5.5-4.44 9.963-9.932 10h-.138C6.438 21.962 2 17.5 2 12Zm10-5c-1.84 0-3.333 1.455-3.333 3.25S10.159 13.5 12 13.5c1.84 0 3.333-1.455 3.333-3.25S13.841 7 12 7Z" clip-rule="evenodd"/>
31
- </svg>
32
-
33
- </button>
17
+ <div class="flex items-center ms-3 ">
18
+ <div>
19
+ <button type="button" class="flex text-sm bg-header-bg-hover rounded-full focus:ring-4 focus:ring-nav-menu-devider dark:focus:ring-nav-menu-devider dark:bg-header-bg-hover" aria-expanded="false" data-dropdown-toggle="dropdown-user">
20
+ <span class="sr-only">Open user menu</span>
21
+ <svg class="w-8 h-8 text-nav-menu-icons dark:text-header-icons" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 24 24">
22
+ <path fill-rule="evenodd" d="M12 20a7.966 7.966 0 0 1-5.002-1.756l.002.001v-.683c0-1.794 1.492-3.25 3.333-3.25h3.334c1.84 0 3.333 1.456 3.333 3.25v.683A7.966 7.966 0 0 1 12 20ZM2 12C2 6.477 6.477 2 12 2s10 4.477 10 10c0 5.5-4.44 9.963-9.932 10h-.138C6.438 21.962 2 17.5 2 12Zm10-5c-1.84 0-3.333 1.455-3.333 3.25S10.159 13.5 12 13.5c1.84 0 3.333-1.455 3.333-3.25S13.841 7 12 7Z" clip-rule="evenodd"/>
23
+ </svg>
24
+ </button>
25
+ </div>
26
+ <div class="z-50 hidden my-4 text-base list-none bg-white divide-y divide-gray-100 rounded shadow dark:shadow-black dark:bg-nav-menu-bg dark:divide-nav-menu-devider dark:shadow-black" id="dropdown-user">
27
+ <div class="px-4 py-3" role="none">
28
+ <p class="text-sm text-gray-900 dark:text-header-text" role="none" v-if="coreStore.userFullname">
29
+ {{ coreStore.userFullname }}
30
+ </p>
31
+ <p class="text-sm font-medium text-gray-900 truncate dark:text-nav-menu-text" role="none">
32
+ {{ coreStore.username }}
33
+ </p>
34
34
  </div>
35
- <div class="z-50 hidden my-4 text-base list-none bg-white divide-y divide-gray-100 rounded shadow dark:shadow-black dark:bg-gray-700 dark:divide-gray-600 dark:shadow-black" id="dropdown-user">
36
- <div class="px-4 py-3" role="none">
37
- <p class="text-sm text-gray-900 dark:text-white" role="none" v-if="coreStore.userFullname">
38
- {{ coreStore.userFullname }}
39
- </p>
40
- <p class="text-sm font-medium text-gray-900 truncate dark:text-gray-300" role="none">
41
- {{ coreStore.username }}
42
- </p>
43
- </div>
44
- <ul class="py-1" role="none">
45
- <li >
46
- <span @click="toggleTheme" class=" cursor-pointer flex items-center gap-1 block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-600 dark:hover:text-white" role="menuitem">
47
- {{ theme === 'dark' ? 'Light' : 'Dark' }}
48
- <IconMoonSolid class="w-5 h-5 text-blue-300
49
- " v-if="theme !== 'dark'"/>
50
- <IconSunSolid class="w-5 h-5 text-yellow-300
51
- " v-else/>
52
- mode
53
- </span>
54
- </li>
55
-
56
- <li>
57
- <button @click="logout" class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-600 dark:hover:text-white" role="menuitem">Sign out</button>
35
+ <ul class="py-1" role="none">
36
+ <li>
37
+ <span @click="toggleTheme" class="cursor-pointer flex items-center gap-1 block px-4 py-2 text-sm text-black hover:bg-html-bg dark:text-nav-menu-text-hover dark:hover:bg-nav-menu-hover dark:hover:text-nav-menu-text-active" role="menuitem">
38
+ {{ theme === 'dark' ? 'Light' : 'Dark' }}
39
+ <IconMoonSolid class="w-5 h-5 text-blue-300" v-if="theme !== 'dark'" />
40
+ <IconSunSolid class="w-5 h-5 text-yellow-300" v-else />
41
+ mode
42
+ </span>
58
43
  </li>
59
- </ul>
60
- </div>
44
+ <li>
45
+ <button @click="logout" class="cursor-pointer flex items-center gap-1 block px-4 py-2 text-sm text-black hover:bg-html-bg dark:text-nav-menu-text-hover dark:hover:bg-nav-menu-hover dark:hover:text-nav-menu-text-active w-full" role="menuitem">Sign out</button>
46
+ </li>
47
+ </ul>
61
48
  </div>
62
49
  </div>
50
+ </div>
63
51
  </div>
64
52
  </div>
65
- </nav>
53
+ </nav>
54
+
66
55
 
67
56
 
68
57
  <aside
69
58
  v-if="loggedIn"
70
59
 
71
- id="logo-sidebar" class="fixed top-0 left-0 z-10 w-64 h-screen pt-20 transition-transform -translate-x-full bg-white border-r border-gray-200 sm:translate-x-0 dark:bg-gray-800 dark:border-gray-700" aria-label="Sidebar">
72
- <div class="h-full px-3 pb-4 overflow-y-auto bg-white dark:bg-gray-800">
60
+ id="logo-sidebar" class="fixed border-none top-0 left-0 z-50 w-64 h-screen transition-transform -translate-x-full bg-nav-menu-bg border-r border- sm:translate-x-0 dark:bg-gray-800 dark:border-gray-700" aria-label="Sidebar">
61
+ <div class="h-full px-3 pb-4 overflow-y-auto bg-nav-menu-bg dark:bg-gray-800">
62
+ <div class="flex ms-2 md:me-24 m-4 ">
63
+ <img src="https://flowbite.com/docs/images/logo.svg" class="h-8 me-3" alt="FlowBite Logo" />
64
+ <span class="self-center text-xl font-semibold sm:text-2xl whitespace-nowrap dark:text-header-text text-header-logo-color">
65
+ {{ coreStore.config?.brandName }}
66
+ </span>
67
+ </div>
73
68
  <ul class="space-y-2 font-medium">
74
69
  <template v-for="(item, i) in coreStore.menu" :key="`menu-${i}`">
75
- <div v-if="item.type === 'divider'" class="border-t border-gray-200 dark:border-gray-700"></div>
70
+ <div v-if="item.type === 'divider'" class="border-t border-nav-menu-devider dark:border-gray-700"></div>
76
71
  <div v-else-if="item.type === 'gap'" class="flex items-center justify-center h-8"></div>
77
72
  <div v-else-if="item.type === 'heading'" class="flex items-center justify-left pl-2 h-8 text-gray-400 dark:text-gray-400
78
73
  ">{{ item.label }}</div>
79
74
 
80
75
 
81
76
  <li v-else-if="item.children">
82
- <button type="button" class="flex items-center w-full p-2 text-base text-gray-900 transition duration-75 rounded-lg group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700"
77
+ <button type="button" class="flex items-center w-full p-2 text-base text-nav-menu-text transition duration-75 group hover:bg-nav-menu-bg-hover dark:text-white dark:hover:bg-gray-700"
83
78
  :aria-controls="`dropdown-example${i}`"
84
79
  :data-collapse-toggle="`dropdown-example${i}`"
85
80
  >
86
- <component v-if="item.icon" :is="getIcon(item.icon)" class="w-5 h-5 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white" ></component>
81
+ <component v-if="item.icon" :is="getIcon(item.icon)" class="w-5 h-5 text-gray-500 transition duration-75 dark:text-gray-400 dark:group-hover:text-white" ></component>
87
82
 
88
83
  <span class="flex-1 ms-3 text-left rtl:text-right whitespace-nowrap">{{ item.label }}</span>
89
84
  <svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 10 6">
@@ -135,6 +130,7 @@ import { useRoute, useRouter } from 'vue-router';
135
130
  import { getIcon } from '@/utils';
136
131
  import { useHead } from 'unhead'
137
132
  import { createHead } from 'unhead'
133
+ // import { link } from 'fs';
138
134
  const coreStore = useCoreStore();
139
135
 
140
136
 
@@ -182,6 +178,12 @@ onMounted(async () => {
182
178
  title.value = coreStore.config.title || 'Admin Forth';
183
179
  useHead({
184
180
  title: title.value,
181
+ link: [
182
+ {
183
+ rel: 'icon',
184
+ href: coreStore.config.favicon || '/favicon.ico',
185
+ },
186
+ ],
185
187
 
186
188
  })
187
189
  })
@@ -9,7 +9,8 @@
9
9
  :placeholder="selectedItems.length ? '' : 'Select...'"
10
10
  />
11
11
  <div class="absolute inset-y-0 left-2 flex items-center pr-2 flex-wrap">
12
- <div v-for="item in selectedItems" :key="item.name" class="bg-blue-100 text-blue-800 text-xs font-medium me-2 px-2.5 py-0.5 rounded dark:bg-blue-900 dark:text-blue-300">
12
+ {{ }}
13
+ <div v-for="item in selectedItems" :key="item?.name" class="bg-blue-100 text-blue-800 text-xs font-medium me-2 px-2.5 py-0.5 rounded dark:bg-blue-900 dark:text-blue-300">
13
14
  <span>{{ item.label }}</span>
14
15
  <button
15
16
  type="button"
@@ -1,11 +1,11 @@
1
1
  <template>
2
2
  <RouterLink
3
3
  :to="{name: item.resourceId ? 'resource-list' : item.path, params: item.resourceId ? { resourceId: item.resourceId }: {}}"
4
- class="flex items-center py-2 text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-600 dark:hover:text-white" role="menuitem"
4
+ class="flex items-center py-2 text-nav-menu-text hover:bg-nav-menu-bg-hover active:bg-nav-menu-bg-active" role="menuitem"
5
5
  :class="{
6
6
  'px-4': isChild,
7
7
  'px-2': !isChild,
8
- 'bg-blue-100 dark:bg-gray-700': item.resourceId ?
8
+ 'bg-nav-menu-bg-active dark:bg-gray-700': item.resourceId ?
9
9
  ($route.params.resourceId === item.resourceId && $route.name === 'resource-list') :
10
10
  ($route.name === item.path)
11
11
  }"
@@ -2,11 +2,11 @@
2
2
  <div>
3
3
 
4
4
  <div
5
- class="relative shadow-md sm:rounded-lg dark:shadow-2xl dark:shadow-black"
5
+ class="relative shadow-resourse-form-shadow sm:rounded-lg dark:shadow-2xl dark:shadow-black"
6
6
  >
7
7
  <form autocomplete="off" @submit.prevent>
8
8
  <table class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
9
- <thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
9
+ <thead class="text-xs text-gray-700 uppercase bg-form-view-heading dark:bg-gray-700 dark:text-gray-400">
10
10
  <tr>
11
11
  <th scope="col" class="px-6 py-3">
12
12
  Field
@@ -18,7 +18,7 @@
18
18
  </thead>
19
19
  <tbody>
20
20
  <tr v-for="column, i in editableColumns" :key="column.name"
21
- class="odd:bg-white odd:dark:bg-gray-900 even:bg-gray-50 even:dark:bg-gray-800 border-b dark:border-gray-700"
21
+ class="bg-form-view-bg dark:bg-gray-800 border-b dark:border-gray-700"
22
22
  >
23
23
  <!-- if column is in customComponentsPerColumn, use this component. If not, use this code -->
24
24
  <template v-if="customComponentsPerColumn[column.name]">
@@ -65,7 +65,7 @@
65
65
  </BreadcrumbsWithButtons>
66
66
 
67
67
  <!-- table -->
68
- <div class="relative overflow-x-auto shadow-md dark:shadow-black sm:rounded-lg dark:s">
68
+ <div class="relative overflow-x-auto shadow-list-table-shadow dark:shadow-black dark:s">
69
69
 
70
70
 
71
71
  <!-- skelet loader -->
@@ -90,7 +90,7 @@
90
90
  </div>
91
91
 
92
92
  <table v-else class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
93
- <thead class="text-xs text-gray-700 bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
93
+ <thead class="text-xs text-view-table-heading-text bg-list-view-table-heading dark:bg-gray-700 dark:text-gray-400">
94
94
  <tr>
95
95
  <th scope="col" class="p-4">
96
96
  <div v-if="rows && rows.length" class="flex items-center">
@@ -127,7 +127,7 @@
127
127
  </tr>
128
128
  </thead>
129
129
  <tbody>
130
- <tr v-if="!rows" class="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
130
+ <tr v-if="!rows" class="bg-list-view-table-bg border-b dark:bg-gray-800 dark:border-gray-700">
131
131
  <td :colspan="coreStore.resourceColumns.length + 2">
132
132
 
133
133
  <div role="status"
@@ -171,7 +171,7 @@
171
171
  </div>
172
172
  </td>
173
173
  </tr>
174
- <tr v-else-if="rows.length === 0" class="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
174
+ <tr v-else-if="rows.length === 0" class="bg-list-view-table-bg border-b dark:bg-gray-800 dark:border-gray-700">
175
175
  <td :colspan="coreStore.resourceColumns.length + 2">
176
176
 
177
177
  <div id="toast-simple"
@@ -185,7 +185,7 @@
185
185
  </tr>
186
186
 
187
187
  <tr v-else v-for="(row, rowI) in rows" :key="row.id"
188
- class="bg-white border-b dark:bg-gray-800 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600">
188
+ class="bg-list-view-table-bg border-b dark:bg-gray-800 border-list-view-border-color dark:border-gray-700 hover:bg-list-view-table-row-hover dark:hover:bg-gray-600">
189
189
  <td class="w-4 p-4">
190
190
  <div class="flex items center">
191
191
  <input
@@ -27,10 +27,10 @@
27
27
  </div>
28
28
  <div
29
29
  v-else
30
- class="relative overflow-x-auto shadow-md sm:rounded-lg"
30
+ class="relative overflow-x-auto shadow-resourse-form-shadow "
31
31
  >
32
32
  <table class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
33
- <thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
33
+ <thead class="text-xs text-gray-700 uppercase bg-form-view-heading dark:bg-gray-700 dark:text-gray-400">
34
34
  <tr>
35
35
  <th scope="col" class="px-6 py-3">
36
36
  Field
@@ -42,7 +42,7 @@
42
42
  </thead>
43
43
  <tbody>
44
44
  <tr v-for="column in coreStore.resourceColumns?.filter(c => c.showIn.includes('show'))" :key="column.name"
45
- class="odd:bg-white odd:dark:bg-gray-900 even:bg-gray-50 even:dark:bg-gray-800 border-b dark:border-gray-700"
45
+ class="bg-form-view-bg odd:dark:bg-gray-900 even:dark:bg-gray-800 border-b dark:border-gray-700"
46
46
  >
47
47
  <td class="px-6 py-4 whitespace-nowrap">
48
48
  {{ column.label }}
@@ -1,9 +1,12 @@
1
1
  /** @type {import('tailwindcss').Config} */
2
2
  export default {
3
- content: ["./src/**/*.{vue, js}", "./node_modules/flowbite/**/*.js"],
3
+ content: ["./src/**/*.{vue, js}","./src/*.{vue, js}", "./index.html", "./node_modules/flowbite/**/*.js"],
4
4
  theme: {
5
- extend: {},
5
+ extend: {
6
+ /* IMPORTANT:ADMINFORTH TAILWIND STYLES */
7
+ }
6
8
  },
9
+
7
10
  darkMode: 'class',
8
11
  plugins: [
9
12
  require('flowbite/plugin'),
@@ -104,12 +104,14 @@ export type AdminForthConfig = {
104
104
  customization?: {
105
105
  customComponentsDir?: string,
106
106
  vueUsesFile?: string,
107
+ customPublicDir?: string,
107
108
  },
108
109
  baseUrl?: string,
109
110
  brandName?: string,
110
111
  datesFormat?: string,
111
112
  deleteConfirmation?: boolean,
112
113
  title?: string,
114
+ styles?: Object,
113
115
  }
114
116
 
115
117
  export type AllowedActions = {