@stacksjs/defaults 0.70.206 → 0.70.208

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 (408) hide show
  1. package/TODO.md +21 -0
  2. package/ai/AGENTS.md +79 -0
  3. package/ai/README.md +45 -0
  4. package/ai/claude/launch.json +12 -0
  5. package/ai/skills/stacks-actions/SKILL.md +128 -0
  6. package/ai/skills/stacks-ai/SKILL.md +276 -0
  7. package/ai/skills/stacks-alias/SKILL.md +94 -0
  8. package/ai/skills/stacks-analytics/SKILL.md +91 -0
  9. package/ai/skills/stacks-api/SKILL.md +738 -0
  10. package/ai/skills/stacks-arrays/SKILL.md +277 -0
  11. package/ai/skills/stacks-auth/SKILL.md +422 -0
  12. package/ai/skills/stacks-auto-imports/SKILL.md +138 -0
  13. package/ai/skills/stacks-brandkit/SKILL.md +811 -0
  14. package/ai/skills/stacks-browse/SKILL.md +127 -0
  15. package/ai/skills/stacks-browse/scripts/browse.ts +492 -0
  16. package/ai/skills/stacks-browser/SKILL.md +145 -0
  17. package/ai/skills/stacks-buddy/SKILL.md +676 -0
  18. package/ai/skills/stacks-build/SKILL.md +163 -0
  19. package/ai/skills/stacks-cache/SKILL.md +125 -0
  20. package/ai/skills/stacks-calendar/SKILL.md +113 -0
  21. package/ai/skills/stacks-chat/SKILL.md +371 -0
  22. package/ai/skills/stacks-cli/SKILL.md +112 -0
  23. package/ai/skills/stacks-cloud/SKILL.md +192 -0
  24. package/ai/skills/stacks-cms/SKILL.md +217 -0
  25. package/ai/skills/stacks-collections/SKILL.md +82 -0
  26. package/ai/skills/stacks-commerce/SKILL.md +114 -0
  27. package/ai/skills/stacks-composables/SKILL.md +161 -0
  28. package/ai/skills/stacks-config/SKILL.md +144 -0
  29. package/ai/skills/stacks-configuration/SKILL.md +154 -0
  30. package/ai/skills/stacks-cron/SKILL.md +123 -0
  31. package/ai/skills/stacks-crosswind/SKILL.md +190 -0
  32. package/ai/skills/stacks-dashboard/SKILL.md +173 -0
  33. package/ai/skills/stacks-database/SKILL.md +286 -0
  34. package/ai/skills/stacks-datetime/SKILL.md +269 -0
  35. package/ai/skills/stacks-dependencies/SKILL.md +111 -0
  36. package/ai/skills/stacks-deploy/SKILL.md +102 -0
  37. package/ai/skills/stacks-design-brutalist/SKILL.md +110 -0
  38. package/ai/skills/stacks-design-minimalist/SKILL.md +115 -0
  39. package/ai/skills/stacks-design-output/SKILL.md +55 -0
  40. package/ai/skills/stacks-design-soft/SKILL.md +156 -0
  41. package/ai/skills/stacks-design-taste/SKILL.md +1012 -0
  42. package/ai/skills/stacks-design-taste-codex/SKILL.md +294 -0
  43. package/ai/skills/stacks-desktop/SKILL.md +78 -0
  44. package/ai/skills/stacks-development/SKILL.md +298 -0
  45. package/ai/skills/stacks-dns/SKILL.md +149 -0
  46. package/ai/skills/stacks-docs/SKILL.md +109 -0
  47. package/ai/skills/stacks-email/SKILL.md +236 -0
  48. package/ai/skills/stacks-enums/SKILL.md +100 -0
  49. package/ai/skills/stacks-env/SKILL.md +181 -0
  50. package/ai/skills/stacks-error-handling/SKILL.md +137 -0
  51. package/ai/skills/stacks-events/SKILL.md +228 -0
  52. package/ai/skills/stacks-faker/SKILL.md +158 -0
  53. package/ai/skills/stacks-git/SKILL.md +158 -0
  54. package/ai/skills/stacks-guard/SKILL.md +98 -0
  55. package/ai/skills/stacks-health/SKILL.md +75 -0
  56. package/ai/skills/stacks-http/SKILL.md +316 -0
  57. package/ai/skills/stacks-i18n/SKILL.md +198 -0
  58. package/ai/skills/stacks-image-to-code/SKILL.md +629 -0
  59. package/ai/skills/stacks-imagegen-mobile/SKILL.md +1474 -0
  60. package/ai/skills/stacks-imagegen-web/SKILL.md +998 -0
  61. package/ai/skills/stacks-investigate/SKILL.md +119 -0
  62. package/ai/skills/stacks-jobs/SKILL.md +136 -0
  63. package/ai/skills/stacks-lint/SKILL.md +184 -0
  64. package/ai/skills/stacks-listeners/SKILL.md +99 -0
  65. package/ai/skills/stacks-logging/SKILL.md +78 -0
  66. package/ai/skills/stacks-mail/SKILL.md +120 -0
  67. package/ai/skills/stacks-middleware/SKILL.md +249 -0
  68. package/ai/skills/stacks-migrations/SKILL.md +105 -0
  69. package/ai/skills/stacks-models/SKILL.md +267 -0
  70. package/ai/skills/stacks-new-feature/SKILL.md +206 -0
  71. package/ai/skills/stacks-notifications/SKILL.md +210 -0
  72. package/ai/skills/stacks-objects/SKILL.md +205 -0
  73. package/ai/skills/stacks-office-hours/SKILL.md +134 -0
  74. package/ai/skills/stacks-orm/SKILL.md +342 -0
  75. package/ai/skills/stacks-path/SKILL.md +118 -0
  76. package/ai/skills/stacks-payments/SKILL.md +373 -0
  77. package/ai/skills/stacks-plan-review/SKILL.md +152 -0
  78. package/ai/skills/stacks-plugins/SKILL.md +149 -0
  79. package/ai/skills/stacks-push/SKILL.md +376 -0
  80. package/ai/skills/stacks-query-builder/SKILL.md +128 -0
  81. package/ai/skills/stacks-queue/SKILL.md +559 -0
  82. package/ai/skills/stacks-realtime/SKILL.md +442 -0
  83. package/ai/skills/stacks-redesign/SKILL.md +182 -0
  84. package/ai/skills/stacks-registry/SKILL.md +58 -0
  85. package/ai/skills/stacks-repl/SKILL.md +80 -0
  86. package/ai/skills/stacks-retro/SKILL.md +122 -0
  87. package/ai/skills/stacks-review/SKILL.md +135 -0
  88. package/ai/skills/stacks-router/SKILL.md +231 -0
  89. package/ai/skills/stacks-routes/SKILL.md +105 -0
  90. package/ai/skills/stacks-scaffolding/SKILL.md +162 -0
  91. package/ai/skills/stacks-scheduler/SKILL.md +363 -0
  92. package/ai/skills/stacks-search-engine/SKILL.md +112 -0
  93. package/ai/skills/stacks-security/SKILL.md +129 -0
  94. package/ai/skills/stacks-security-audit/SKILL.md +128 -0
  95. package/ai/skills/stacks-server/SKILL.md +458 -0
  96. package/ai/skills/stacks-shell/SKILL.md +62 -0
  97. package/ai/skills/stacks-slug/SKILL.md +87 -0
  98. package/ai/skills/stacks-sms/SKILL.md +385 -0
  99. package/ai/skills/stacks-socials/SKILL.md +303 -0
  100. package/ai/skills/stacks-storage/SKILL.md +576 -0
  101. package/ai/skills/stacks-strings/SKILL.md +416 -0
  102. package/ai/skills/stacks-stx/SKILL.md +176 -0
  103. package/ai/skills/stacks-technical-diagrams/LICENSE +22 -0
  104. package/ai/skills/stacks-technical-diagrams/SKILL.md +290 -0
  105. package/ai/skills/stacks-technical-diagrams/agents/openai.yaml +4 -0
  106. package/ai/skills/stacks-technical-diagrams/assets/template.html +1252 -0
  107. package/ai/skills/stacks-technical-diagrams/bin/technical-diagrams.mjs +289 -0
  108. package/ai/skills/stacks-technical-diagrams/bunfig.toml +1 -0
  109. package/ai/skills/stacks-technical-diagrams/examples/agent-run.lifecycle.json +64 -0
  110. package/ai/skills/stacks-technical-diagrams/examples/agent-tool-call.workflow.json +88 -0
  111. package/ai/skills/stacks-technical-diagrams/examples/cache-miss-request.sequence.json +75 -0
  112. package/ai/skills/stacks-technical-diagrams/examples/product-analytics.dataflow.json +70 -0
  113. package/ai/skills/stacks-technical-diagrams/examples/web-app.architecture.json +41 -0
  114. package/ai/skills/stacks-technical-diagrams/renderers/architecture/grid.mjs +62 -0
  115. package/ai/skills/stacks-technical-diagrams/renderers/architecture/render-architecture.mjs +371 -0
  116. package/ai/skills/stacks-technical-diagrams/renderers/dataflow/README.md +82 -0
  117. package/ai/skills/stacks-technical-diagrams/renderers/dataflow/render-dataflow.mjs +295 -0
  118. package/ai/skills/stacks-technical-diagrams/renderers/lifecycle/README.md +91 -0
  119. package/ai/skills/stacks-technical-diagrams/renderers/lifecycle/render-lifecycle.mjs +384 -0
  120. package/ai/skills/stacks-technical-diagrams/renderers/sequence/README.md +84 -0
  121. package/ai/skills/stacks-technical-diagrams/renderers/sequence/render-sequence.mjs +257 -0
  122. package/ai/skills/stacks-technical-diagrams/renderers/shared/cli.mjs +42 -0
  123. package/ai/skills/stacks-technical-diagrams/renderers/shared/generated-validators.mjs +13 -0
  124. package/ai/skills/stacks-technical-diagrams/renderers/shared/geometry.mjs +230 -0
  125. package/ai/skills/stacks-technical-diagrams/renderers/shared/layout-report.mjs +40 -0
  126. package/ai/skills/stacks-technical-diagrams/renderers/shared/utils.mjs +88 -0
  127. package/ai/skills/stacks-technical-diagrams/renderers/shared/validator.mjs +40 -0
  128. package/ai/skills/stacks-technical-diagrams/renderers/workflow/README.md +103 -0
  129. package/ai/skills/stacks-technical-diagrams/renderers/workflow/render-workflow.mjs +481 -0
  130. package/ai/skills/stacks-technical-diagrams/schemas/README.md +68 -0
  131. package/ai/skills/stacks-technical-diagrams/schemas/architecture.schema.json +121 -0
  132. package/ai/skills/stacks-technical-diagrams/schemas/common.schema.json +43 -0
  133. package/ai/skills/stacks-technical-diagrams/schemas/dataflow.schema.json +221 -0
  134. package/ai/skills/stacks-technical-diagrams/schemas/lifecycle.schema.json +241 -0
  135. package/ai/skills/stacks-technical-diagrams/schemas/sequence.schema.json +186 -0
  136. package/ai/skills/stacks-technical-diagrams/schemas/workflow.schema.json +332 -0
  137. package/ai/skills/stacks-technical-diagrams/scripts/check-render-output.mjs +297 -0
  138. package/ai/skills/stacks-technical-diagrams/scripts/render-examples.mjs +28 -0
  139. package/ai/skills/stacks-testing/SKILL.md +129 -0
  140. package/ai/skills/stacks-tunnel/SKILL.md +125 -0
  141. package/ai/skills/stacks-types/SKILL.md +178 -0
  142. package/ai/skills/stacks-ui/SKILL.md +246 -0
  143. package/ai/skills/stacks-utils/SKILL.md +444 -0
  144. package/ai/skills/stacks-validation/SKILL.md +371 -0
  145. package/ai/skills/stacks-whois/SKILL.md +315 -0
  146. package/assets/world-map-data.ts +121 -0
  147. package/bootstrap.ts +114 -0
  148. package/docs/api-examples.md +46 -0
  149. package/docs/index.md +24 -0
  150. package/docs/markdown-examples.md +87 -0
  151. package/functions/analytics.ts +97 -0
  152. package/functions/api.ts +143 -0
  153. package/functions/auth.ts +208 -0
  154. package/functions/billing/payments.ts +149 -0
  155. package/functions/blog.ts +120 -0
  156. package/functions/cms/categorizables.ts +107 -0
  157. package/functions/cms/pages.ts +108 -0
  158. package/functions/cms/posts.ts +100 -0
  159. package/functions/cms/taggables.ts +102 -0
  160. package/functions/commerce/coupons.ts +128 -0
  161. package/functions/commerce/customers.ts +128 -0
  162. package/functions/commerce/gift-cards.ts +119 -0
  163. package/functions/commerce/orders.ts +112 -0
  164. package/functions/commerce/payments.ts +119 -0
  165. package/functions/commerce/products/categories.ts +123 -0
  166. package/functions/commerce/products/manufacturers.ts +123 -0
  167. package/functions/commerce/products/products.ts +123 -0
  168. package/functions/commerce/products/reviews.ts +123 -0
  169. package/functions/commerce/products/units.ts +123 -0
  170. package/functions/commerce/products/variants.ts +123 -0
  171. package/functions/commerce/shippings/delivery-routes.ts +123 -0
  172. package/functions/commerce/shippings/digital-deliveries.ts +119 -0
  173. package/functions/commerce/shippings/drivers.ts +123 -0
  174. package/functions/commerce/shippings/license-keys.ts +123 -0
  175. package/functions/commerce/shippings/shipping-methods.ts +123 -0
  176. package/functions/commerce/shippings/shipping-rates.ts +119 -0
  177. package/functions/commerce/shippings/shipping-zones.ts +119 -0
  178. package/functions/commerce/taxes.ts +119 -0
  179. package/functions/commerce/waitlist/products.ts +123 -0
  180. package/functions/commerce/waitlist/restaurants.ts +123 -0
  181. package/functions/craft.ts +107 -0
  182. package/functions/dashboard.ts +153 -0
  183. package/functions/inbox.ts +95 -0
  184. package/functions/jobs.ts +86 -0
  185. package/functions/monitoring/errors.ts +295 -0
  186. package/functions/queue.ts +111 -0
  187. package/functions/realtime/websockets.ts +96 -0
  188. package/functions/realtime.ts +52 -0
  189. package/functions/releases.ts +49 -0
  190. package/functions/search.ts +126 -0
  191. package/functions/toasts.ts +95 -0
  192. package/functions/uploads.ts +216 -0
  193. package/ide/.gitignore +4 -0
  194. package/ide/cursor/rules/auto-imports.mdc +574 -0
  195. package/ide/cursor/rules/code-style.mdc +12 -0
  196. package/ide/cursor/rules/documentation.mdc +9 -0
  197. package/ide/cursor/rules/error-handling-validation.mdc +11 -0
  198. package/ide/cursor/rules/key-conventions.mdc +11 -0
  199. package/ide/cursor/rules/project-structure.mdc +169 -0
  200. package/ide/cursor/rules/readme.mdc +318 -0
  201. package/ide/cursor/rules/syntax-formatting.mdc +9 -0
  202. package/ide/cursor/rules/testing.mdc +10 -0
  203. package/ide/cursor/rules/typescript.mdc +9 -0
  204. package/ide/cursor/rules/ui-styling.mdc +0 -0
  205. package/ide/dictionary.txt +397 -0
  206. package/ide/jetbrains/.fleet/settings.json +4 -0
  207. package/ide/jetbrains/.idea/.gitignore +5 -0
  208. package/ide/jetbrains/.idea/.name +1 -0
  209. package/ide/jetbrains/.idea/inspectionProfiles/Project_Default.xml +6 -0
  210. package/ide/jetbrains/.idea/jsLinters/eslint.xml +7 -0
  211. package/ide/jetbrains/.idea/modules.xml +8 -0
  212. package/ide/jetbrains/.idea/stacks.iml +22 -0
  213. package/ide/jetbrains/.idea/vcs.xml +6 -0
  214. package/ide/jetbrains/.idea/webResources.xml +14 -0
  215. package/ide/jetbrains/IntelliJ IDEA Global Settings +0 -0
  216. package/ide/jetbrains/installed.txt +4 -0
  217. package/ide/jetbrains/options/github-copilot.xml +5 -0
  218. package/ide/jetbrains/options/nodejs.xml +7 -0
  219. package/ide/jetbrains/options/templates.xml +124 -0
  220. package/ide/jetbrains/templates/JavaScript.xml +6 -0
  221. package/ide/jetbrains/templates/Stacks.xml +8 -0
  222. package/ide/vscode/.vscode/README.md +23 -0
  223. package/ide/vscode/.vscode/extensions.json +5 -0
  224. package/ide/vscode/.vscode/settings.json +176 -0
  225. package/ide/vscode/.vscode/stacks.code-snippets +181 -0
  226. package/ide/vscode/LICENSE.md +21 -0
  227. package/ide/vscode/README.md +36 -0
  228. package/ide/vscode/logo.png +0 -0
  229. package/ide/vscode/package.json +79 -0
  230. package/ide/zed/.zed/settings.json +139 -0
  231. package/lang/README.md +28 -0
  232. package/lang/de.yml +14 -0
  233. package/lang/en.yml +15 -0
  234. package/package.json +19 -3
  235. package/project/bootstrap +161 -0
  236. package/project/buddy +175 -0
  237. package/project/storage/framework/tsconfig.app.json +50 -0
  238. package/project/storage/framework/tsconfig.base.json +58 -0
  239. package/routes/core.ts +78 -0
  240. package/routes/dashboard-api.ts +233 -0
  241. package/routes/dashboard.ts +739 -0
  242. package/routes/email.ts +129 -0
  243. package/stores/[name].stx +16 -0
  244. package/stores/git.ts +71 -0
  245. package/stores/payment.ts +474 -0
  246. package/stores/queue.ts +43 -0
  247. package/stores/user.ts +29 -0
  248. package/stx-components-plugin.ts +25 -0
  249. package/styles/design-tokens.css +597 -0
  250. package/types/dashboard.ts +70 -0
  251. package/types/defaults.ts +438 -0
  252. package/vcs/github/CODE_OF_CONDUCT.md +83 -0
  253. package/vcs/github/CONTRIBUTING.md +187 -0
  254. package/vcs/github/EXPLANATIONS.md +41 -0
  255. package/vcs/github/FUNDING.yml +1 -0
  256. package/vcs/github/ISSUE_TEMPLATE/bug_report.yml +49 -0
  257. package/vcs/github/ISSUE_TEMPLATE/config.yml +10 -0
  258. package/vcs/github/ISSUE_TEMPLATE/feature_request.yml +44 -0
  259. package/vcs/github/SECURITY.md +70 -0
  260. package/vcs/github/renovate.json +5 -0
  261. package/vcs/github/stale.yml +14 -0
  262. package/vcs/github/workflows/README.md +16 -0
  263. package/vcs/github/workflows/ci.yml +114 -0
  264. package/vcs/github/workflows/export-size.yml +25 -0
  265. package/vcs/github/workflows/labeler.yml +13 -0
  266. package/vcs/github/workflows/release.yml +219 -0
  267. package/views/[...all].stx +8 -0
  268. package/views/about.md +3 -0
  269. package/views/auth/login.stx +1 -0
  270. package/views/auth/signup.stx +85 -0
  271. package/views/dashboard/.discovered-models.json +542 -0
  272. package/views/dashboard/AUDIT.md +904 -0
  273. package/views/dashboard/[...all].stx +89 -0
  274. package/views/dashboard/access-tokens/index.stx +177 -0
  275. package/views/dashboard/actions/index.stx +129 -0
  276. package/views/dashboard/analytics/blog/index.stx +356 -0
  277. package/views/dashboard/analytics/browsers/index.stx +263 -0
  278. package/views/dashboard/analytics/commerce/sales/index.stx +329 -0
  279. package/views/dashboard/analytics/commerce/web/index.stx +379 -0
  280. package/views/dashboard/analytics/countries/index.stx +289 -0
  281. package/views/dashboard/analytics/devices/index.stx +305 -0
  282. package/views/dashboard/analytics/events/index.stx +536 -0
  283. package/views/dashboard/analytics/index.stx +88 -0
  284. package/views/dashboard/analytics/marketing/index.stx +315 -0
  285. package/views/dashboard/analytics/pages/index.stx +271 -0
  286. package/views/dashboard/analytics/referrers/index.stx +319 -0
  287. package/views/dashboard/analytics/web/index.stx +356 -0
  288. package/views/dashboard/buddy/index.stx +198 -0
  289. package/views/dashboard/ci/index.stx +462 -0
  290. package/views/dashboard/cloud/index.stx +452 -0
  291. package/views/dashboard/commands/index.stx +295 -0
  292. package/views/dashboard/commerce/categories/index.stx +406 -0
  293. package/views/dashboard/commerce/coupons/index.stx +485 -0
  294. package/views/dashboard/commerce/customers/index.stx +410 -0
  295. package/views/dashboard/commerce/dashboard/index.stx +287 -0
  296. package/views/dashboard/commerce/delivery/delivery-routes.stx +305 -0
  297. package/views/dashboard/commerce/delivery/digital-delivery.stx +332 -0
  298. package/views/dashboard/commerce/delivery/drivers.stx +397 -0
  299. package/views/dashboard/commerce/delivery/index.stx +18 -0
  300. package/views/dashboard/commerce/delivery/license-keys.stx +380 -0
  301. package/views/dashboard/commerce/delivery/shipping-methods.stx +346 -0
  302. package/views/dashboard/commerce/delivery/shipping-rates.stx +338 -0
  303. package/views/dashboard/commerce/delivery/shipping-zones.stx +302 -0
  304. package/views/dashboard/commerce/delivery/tabs.ts +25 -0
  305. package/views/dashboard/commerce/gift-cards/index.stx +561 -0
  306. package/views/dashboard/commerce/manufacturers/index.stx +308 -0
  307. package/views/dashboard/commerce/orders/index.stx +247 -0
  308. package/views/dashboard/commerce/payments/index.stx +535 -0
  309. package/views/dashboard/commerce/pos/index.stx +653 -0
  310. package/views/dashboard/commerce/printers/devices/index.stx +273 -0
  311. package/views/dashboard/commerce/printers/receipts/index.stx +308 -0
  312. package/views/dashboard/commerce/products/detail.stx +563 -0
  313. package/views/dashboard/commerce/products/index.stx +370 -0
  314. package/views/dashboard/commerce/reviews/index.stx +656 -0
  315. package/views/dashboard/commerce/reviews/index.ts +0 -0
  316. package/views/dashboard/commerce/taxes/index.stx +377 -0
  317. package/views/dashboard/commerce/units/index.stx +317 -0
  318. package/views/dashboard/commerce/variants/index.stx +319 -0
  319. package/views/dashboard/commerce/waitlist/products.stx +942 -0
  320. package/views/dashboard/commerce/waitlist/restaurant.stx +1024 -0
  321. package/views/dashboard/components/index.stx +330 -0
  322. package/views/dashboard/composables/index.ts +19 -0
  323. package/views/dashboard/composables/useChart.ts +77 -0
  324. package/views/dashboard/composables/useNavigation.ts +99 -0
  325. package/views/dashboard/composables/useRole.ts +58 -0
  326. package/views/dashboard/composables/useTheme.ts +74 -0
  327. package/views/dashboard/content/authors/index.stx +171 -0
  328. package/views/dashboard/content/blog/index.stx +493 -0
  329. package/views/dashboard/content/categories/index.stx +169 -0
  330. package/views/dashboard/content/comments/index.stx +189 -0
  331. package/views/dashboard/content/dashboard.stx +383 -0
  332. package/views/dashboard/content/files/index.stx +706 -0
  333. package/views/dashboard/content/pages/index.stx +174 -0
  334. package/views/dashboard/content/posts/index.stx +269 -0
  335. package/views/dashboard/content/seo/index.stx +240 -0
  336. package/views/dashboard/content/tags/index.stx +167 -0
  337. package/views/dashboard/data/activity/index.stx +261 -0
  338. package/views/dashboard/data/dashboard/index.stx +116 -0
  339. package/views/dashboard/data/subscribers.stx +270 -0
  340. package/views/dashboard/data/teams.stx +275 -0
  341. package/views/dashboard/data/users.stx +279 -0
  342. package/views/dashboard/dependencies/index.stx +178 -0
  343. package/views/dashboard/deployments/[id].stx +234 -0
  344. package/views/dashboard/deployments/index.stx +9 -0
  345. package/views/dashboard/dns/index.stx +163 -0
  346. package/views/dashboard/environment/index.stx +283 -0
  347. package/views/dashboard/errors/index.stx +274 -0
  348. package/views/dashboard/forgot-password.stx +57 -0
  349. package/views/dashboard/functions/index.stx +159 -0
  350. package/views/dashboard/health/index.stx +248 -0
  351. package/views/dashboard/inbox/activity.stx +350 -0
  352. package/views/dashboard/inbox/index.stx +452 -0
  353. package/views/dashboard/inbox/settings.stx +290 -0
  354. package/views/dashboard/index.stx +252 -0
  355. package/views/dashboard/insights/index.stx +529 -0
  356. package/views/dashboard/jobs/[id].stx +430 -0
  357. package/views/dashboard/jobs/history.stx +222 -0
  358. package/views/dashboard/jobs/index.stx +214 -0
  359. package/views/dashboard/kanban/[id].stx +899 -0
  360. package/views/dashboard/kanban/index.stx +260 -0
  361. package/views/dashboard/layouts/default.stx +565 -0
  362. package/views/dashboard/layouts/guest.stx +10 -0
  363. package/views/dashboard/login.stx +48 -0
  364. package/views/dashboard/logs/index.stx +540 -0
  365. package/views/dashboard/mailboxes/index.stx +149 -0
  366. package/views/dashboard/management/permissions/index.stx +490 -0
  367. package/views/dashboard/marketing/campaigns/index.stx +604 -0
  368. package/views/dashboard/marketing/lists/index.stx +514 -0
  369. package/views/dashboard/marketing/reviews/index.stx +475 -0
  370. package/views/dashboard/marketing/social-posts/index.stx +560 -0
  371. package/views/dashboard/models/[model].stx +195 -0
  372. package/views/dashboard/models/index.stx +159 -0
  373. package/views/dashboard/monitoring/errors/index.stx +415 -0
  374. package/views/dashboard/notifications/dashboard.stx +383 -0
  375. package/views/dashboard/notifications/email.stx +336 -0
  376. package/views/dashboard/notifications/history.stx +373 -0
  377. package/views/dashboard/notifications/sms.stx +332 -0
  378. package/views/dashboard/packages/index.stx +195 -0
  379. package/views/dashboard/queries/[id].stx +381 -0
  380. package/views/dashboard/queries/history.stx +227 -0
  381. package/views/dashboard/queries/index.stx +335 -0
  382. package/views/dashboard/queries/slow.stx +318 -0
  383. package/views/dashboard/queue/index.stx +427 -0
  384. package/views/dashboard/realtime/index.stx +429 -0
  385. package/views/dashboard/register.stx +46 -0
  386. package/views/dashboard/releases/index.stx +389 -0
  387. package/views/dashboard/requests/index.stx +462 -0
  388. package/views/dashboard/serverless/index.stx +475 -0
  389. package/views/dashboard/servers/[id].stx +299 -0
  390. package/views/dashboard/servers/index.stx +483 -0
  391. package/views/dashboard/settings/billing.stx +50 -0
  392. package/views/dashboard/settings/index.stx +256 -0
  393. package/views/dashboard/settings/mail.stx +252 -0
  394. package/views/dashboard/stores/auth.ts +123 -0
  395. package/views/dashboard/stores/ci.ts +342 -0
  396. package/views/dashboard/stores/index.ts +129 -0
  397. package/views/dashboard/stores/kanban.ts +723 -0
  398. package/views/dashboard/stores/rbac.ts +350 -0
  399. package/views/dashboard/stx.config.ts +34 -0
  400. package/views/dashboard/teams/[id].stx +170 -0
  401. package/views/forum/category.stx +92 -0
  402. package/views/forum/index.stx +209 -0
  403. package/views/forum/new-topic.stx +113 -0
  404. package/views/forum/profile.stx +1 -0
  405. package/views/forum/topic.stx +143 -0
  406. package/views/hello-world/[name].stx +47 -0
  407. package/views/index.stx +21 -0
  408. package/views/system-tray/index.stx +147 -0
@@ -0,0 +1,289 @@
1
+ @extends('layouts/default')
2
+
3
+ @section('content')
4
+ @title('Dashboard - Country Analytics')
5
+ <PageLayout>
6
+ <div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between mb-6">
7
+ <div class="flex items-center space-x-2">
8
+ <div class="h-5 w-5 text-gray-500 dark:text-neutral-400 i-hugeicons-calendar-03"></div>
9
+ <span class="font-medium text-gray-700 text-sm dark:text-neutral-300">{{ dateRangeDisplay }}</span>
10
+ </div>
11
+
12
+ <div class="flex flex-wrap gap-2 items-center">
13
+ <span class="text-gray-500 text-sm dark:text-neutral-400">compared to</span>
14
+ <div class="relative">
15
+ <select x-model="comparisonType" class="block pl-3 pr-10 py-1.5 w-full text-gray-900 sm:leading-6 sm:text-sm dark:text-white dark:bg-neutral-800 border-0 ring-1 ring-gray-300 ring-inset rounded-md dark:ring-neutral-700 focus:ring-2 focus:ring-blue-600 focus:ring-inset">
16
+ <option value="no-comparison">No comparison</option>
17
+ <option value="previous-period">Previous period</option>
18
+ <option value="previous-year">Previous year</option>
19
+ </select>
20
+ </div>
21
+ <button type="button" class="inline-flex items-center px-3 py-1.5 font-semibold text-gray-900 text-sm dark:text-white bg-white dark:bg-neutral-700 hover:bg-gray-50 dark:hover:bg-neutral-600 ring-1 ring-gray-300 ring-inset rounded-md dark:ring-neutral-600 shadow-sm">
22
+ <div class="mr-1 h-4 w-4 i-hugeicons-settings-01"></div>
23
+ Auto
24
+ </button>
25
+ </div>
26
+ </div>
27
+
28
+ <div class="mb-8">
29
+ <h1 class="font-bold text-2xl text-gray-900 dark:text-white">Country Analytics</h1>
30
+ <p class="mt-1 text-gray-500 text-sm dark:text-neutral-400">Detailed breakdown of visitor locations across your website</p>
31
+ </div>
32
+
33
+ <div class="mb-8 p-4 bg-white dark:bg-neutral-800 rounded-lg shadow">
34
+ <div class="mb-4">
35
+ <h3 class="font-medium leading-6 text-gray-900 text-lg dark:text-white">Top Countries</h3>
36
+ <p class="mt-1 text-gray-500 text-sm dark:text-neutral-400">Visitors by country of origin</p>
37
+ </div>
38
+
39
+ <div class="h-96 w-full">
40
+ <canvas id="countryChart"></canvas>
41
+ </div>
42
+ </div>
43
+
44
+ <div class="mb-8 p-4 bg-white dark:bg-neutral-800 rounded-lg shadow">
45
+ <div class="mb-4">
46
+ <h3 class="font-medium leading-6 text-gray-900 text-lg dark:text-white">World Map</h3>
47
+ <p class="mt-1 text-gray-500 text-sm dark:text-neutral-400">Geographic distribution of visitors</p>
48
+ </div>
49
+
50
+ <div class="flex items-center justify-center h-96 w-full bg-gray-100 dark:bg-neutral-700 rounded-lg">
51
+ <p class="text-gray-500 dark:text-neutral-400">World map visualization would be displayed here</p>
52
+ </div>
53
+ </div>
54
+
55
+ <div class="mb-8">
56
+ <div class="mb-4">
57
+ <h3 class="font-medium text-gray-900 text-lg dark:text-white">Countries</h3>
58
+ </div>
59
+
60
+ <div class="overflow-hidden border border-gray-200 rounded-lg dark:border-neutral-700">
61
+ <table class="min-w-full divide-gray-200 divide-y dark:divide-neutral-700">
62
+ <thead class="bg-gray-50 dark:bg-neutral-700/50">
63
+ <tr>
64
+ <th scope="col" class="px-4 py-3 font-medium text-gray-500 text-left text-xs tracking-wider uppercase dark:text-neutral-300">Country</th>
65
+ <th scope="col" class="px-4 py-3 font-medium text-gray-500 text-right text-xs tracking-wider uppercase dark:text-neutral-300">Visitors</th>
66
+ <th scope="col" class="px-4 py-3 font-medium text-gray-500 text-right text-xs tracking-wider uppercase dark:text-neutral-300">%</th>
67
+ </tr>
68
+ </thead>
69
+ <tbody class="bg-white dark:bg-neutral-800 divide-gray-200 divide-y dark:divide-neutral-700">
70
+ <template :for="(country, index) in countriesData">
71
+ <tr class="relative hover:bg-gray-50 dark:hover:bg-neutral-700/50">
72
+ <td class="px-4 py-3 text-gray-900 text-sm whitespace-nowrap dark:text-white">
73
+ <div class="absolute inset-0 bg-rose-100/50 dark:bg-rose-900/50" style="width: {{ country.percentage }}%"></div>
74
+ <span class="relative z-10"><span class="mr-2">{{ country.flag }}</span>{{ country.name }}</span>
75
+ </td>
76
+ <td class="relative px-4 py-3 text-gray-500 text-right text-sm whitespace-nowrap dark:text-neutral-300">
77
+ <span class="relative z-10">{{ country.visitors }}</span>
78
+ </td>
79
+ <td class="relative px-4 py-3 text-gray-500 text-right text-sm whitespace-nowrap dark:text-neutral-300">
80
+ <span class="relative z-10">{{ country.percentage }}%</span>
81
+ </td>
82
+ </tr>
83
+ </template>
84
+ </tbody>
85
+ </table>
86
+ </div>
87
+ </div>
88
+
89
+ <div class="mb-8">
90
+ <div class="mb-4">
91
+ <h3 class="font-medium text-gray-900 text-lg dark:text-white">Cities</h3>
92
+ <p class="mt-1 text-gray-500 text-sm dark:text-neutral-400">Top cities by visitor count</p>
93
+ </div>
94
+
95
+ <div class="overflow-hidden border border-gray-200 rounded-lg dark:border-neutral-700">
96
+ <table class="min-w-full divide-gray-200 divide-y dark:divide-neutral-700">
97
+ <thead class="bg-gray-50 dark:bg-neutral-700/50">
98
+ <tr>
99
+ <th scope="col" class="px-4 py-3 font-medium text-gray-500 text-left text-xs tracking-wider uppercase dark:text-neutral-300">City</th>
100
+ <th scope="col" class="px-4 py-3 font-medium text-gray-500 text-left text-xs tracking-wider uppercase dark:text-neutral-300">Country</th>
101
+ <th scope="col" class="px-4 py-3 font-medium text-gray-500 text-right text-xs tracking-wider uppercase dark:text-neutral-300">Visitors</th>
102
+ <th scope="col" class="px-4 py-3 font-medium text-gray-500 text-right text-xs tracking-wider uppercase dark:text-neutral-300">%</th>
103
+ </tr>
104
+ </thead>
105
+ <tbody class="bg-white dark:bg-neutral-800 divide-gray-200 divide-y dark:divide-neutral-700">
106
+ <template :for="(city, index) in citiesData">
107
+ <tr class="relative hover:bg-gray-50 dark:hover:bg-neutral-700/50">
108
+ <td class="px-4 py-3 text-gray-900 text-sm whitespace-nowrap dark:text-white">
109
+ <div class="absolute inset-0 bg-blue-100/50 dark:bg-blue-900/50" style="width: {{ city.percentage }}%"></div>
110
+ <span class="relative z-10">{{ city.name }}</span>
111
+ </td>
112
+ <td class="relative px-4 py-3 text-gray-900 text-sm whitespace-nowrap dark:text-white">
113
+ <span class="relative z-10">{{ city.country }}</span>
114
+ </td>
115
+ <td class="relative px-4 py-3 text-gray-500 text-right text-sm whitespace-nowrap dark:text-neutral-300">
116
+ <span class="relative z-10">{{ city.visitors }}</span>
117
+ </td>
118
+ <td class="relative px-4 py-3 text-gray-500 text-right text-sm whitespace-nowrap dark:text-neutral-300">
119
+ <span class="relative z-10">{{ city.percentage }}%</span>
120
+ </td>
121
+ </tr>
122
+ </template>
123
+ </tbody>
124
+ </table>
125
+ </div>
126
+ </div>
127
+
128
+ <div>
129
+ <div class="mb-4">
130
+ <h3 class="font-medium text-gray-900 text-lg dark:text-white">Languages</h3>
131
+ <p class="mt-1 text-gray-500 text-sm dark:text-neutral-400">Browser language settings of visitors</p>
132
+ </div>
133
+
134
+ <div class="overflow-hidden border border-gray-200 rounded-lg dark:border-neutral-700">
135
+ <table class="min-w-full divide-gray-200 divide-y dark:divide-neutral-700">
136
+ <thead class="bg-gray-50 dark:bg-neutral-700/50">
137
+ <tr>
138
+ <th scope="col" class="px-4 py-3 font-medium text-gray-500 text-left text-xs tracking-wider uppercase dark:text-neutral-300">Language</th>
139
+ <th scope="col" class="px-4 py-3 font-medium text-gray-500 text-left text-xs tracking-wider uppercase dark:text-neutral-300">Code</th>
140
+ <th scope="col" class="px-4 py-3 font-medium text-gray-500 text-right text-xs tracking-wider uppercase dark:text-neutral-300">Visitors</th>
141
+ <th scope="col" class="px-4 py-3 font-medium text-gray-500 text-right text-xs tracking-wider uppercase dark:text-neutral-300">%</th>
142
+ </tr>
143
+ </thead>
144
+ <tbody class="bg-white dark:bg-neutral-800 divide-gray-200 divide-y dark:divide-neutral-700">
145
+ <template :for="(language, index) in languagesData">
146
+ <tr class="relative hover:bg-gray-50 dark:hover:bg-neutral-700/50">
147
+ <td class="px-4 py-3 text-gray-900 text-sm whitespace-nowrap dark:text-white">
148
+ <div class="absolute inset-0 bg-green-100/50 dark:bg-green-900/50" style="width: {{ language.percentage }}%"></div>
149
+ <span class="relative z-10">{{ language.name }}</span>
150
+ </td>
151
+ <td class="relative px-4 py-3 text-gray-900 text-sm whitespace-nowrap dark:text-white">
152
+ <span class="relative z-10">{{ language.code }}</span>
153
+ </td>
154
+ <td class="relative px-4 py-3 text-gray-500 text-right text-sm whitespace-nowrap dark:text-neutral-300">
155
+ <span class="relative z-10">{{ language.visitors }}</span>
156
+ </td>
157
+ <td class="relative px-4 py-3 text-gray-500 text-right text-sm whitespace-nowrap dark:text-neutral-300">
158
+ <span class="relative z-10">{{ language.percentage }}%</span>
159
+ </td>
160
+ </tr>
161
+ </template>
162
+ </tbody>
163
+ </table>
164
+ </div>
165
+ </div>
166
+ </PageLayout>
167
+ <script client>
168
+
169
+ interface CountryRow {
170
+ name: string
171
+ visitors: number
172
+ percentage: number
173
+ flag: string
174
+ code?: string
175
+ }
176
+
177
+ interface CityRow {
178
+ name: string
179
+ country: string
180
+ visitors: number
181
+ percentage: number
182
+ }
183
+
184
+ interface LanguageRow {
185
+ name: string
186
+ code: string
187
+ visitors: number
188
+ percentage: number
189
+ }
190
+
191
+ interface ChartLike { destroy: () => void }
192
+ type ChartCtor = new (canvas: HTMLElement, config: { type: string, data: unknown, options?: unknown }) => ChartLike
193
+
194
+ const dateRangeDisplay = state('All Time: Sep 7, 2023 to Mar 6, 2025')
195
+ const comparisonType = state('no-comparison')
196
+
197
+ const countriesData = state<CountryRow[]>([
198
+ { name: 'United States of America', visitors: 768, flag: '🇺🇸', code: 'US', percentage: 35 },
199
+ { name: 'Germany', visitors: 140, flag: '🇩🇪', code: 'DE', percentage: 12 },
200
+ { name: 'United Kingdom', visitors: 87, flag: '🇬🇧', code: 'GB', percentage: 8 },
201
+ { name: 'India', visitors: 83, flag: '🇮🇳', code: 'IN', percentage: 7 },
202
+ { name: 'Indonesia', visitors: 80, flag: '🇮🇩', code: 'ID', percentage: 7 },
203
+ { name: 'Canada', visitors: 75, flag: '🇨🇦', code: 'CA', percentage: 6 },
204
+ { name: 'Australia', visitors: 68, flag: '🇦🇺', code: 'AU', percentage: 6 },
205
+ { name: 'France', visitors: 62, flag: '🇫🇷', code: 'FR', percentage: 5 },
206
+ { name: 'Brazil', visitors: 58, flag: '🇧🇷', code: 'BR', percentage: 5 },
207
+ { name: 'Japan', visitors: 52, flag: '🇯🇵', code: 'JP', percentage: 4 },
208
+ { name: 'Netherlands', visitors: 45, flag: '🇳🇱', code: 'NL', percentage: 4 },
209
+ { name: 'Spain', visitors: 42, flag: '🇪🇸', code: 'ES', percentage: 3 },
210
+ ])
211
+
212
+ const citiesData = state<CityRow[]>([
213
+ { name: 'New York', country: 'United States of America', visitors: 120, percentage: 10 },
214
+ { name: 'London', country: 'United Kingdom', visitors: 87, percentage: 7 },
215
+ { name: 'Berlin', country: 'Germany', visitors: 75, percentage: 6 },
216
+ { name: 'San Francisco', country: 'United States of America', visitors: 68, percentage: 6 },
217
+ { name: 'Mumbai', country: 'India', visitors: 65, percentage: 5 },
218
+ { name: 'Toronto', country: 'Canada', visitors: 62, percentage: 5 },
219
+ { name: 'Jakarta', country: 'Indonesia', visitors: 60, percentage: 5 },
220
+ { name: 'Sydney', country: 'Australia', visitors: 58, percentage: 5 },
221
+ { name: 'Paris', country: 'France', visitors: 55, percentage: 4 },
222
+ { name: 'Los Angeles', country: 'United States of America', visitors: 52, percentage: 4 },
223
+ ])
224
+
225
+ const languagesData = state<LanguageRow[]>([
226
+ { name: 'English', code: 'en-US', visitors: 980, percentage: 45 },
227
+ { name: 'German', code: 'de-DE', visitors: 140, percentage: 12 },
228
+ { name: 'English (UK)', code: 'en-GB', visitors: 87, percentage: 8 },
229
+ { name: 'Hindi', code: 'hi-IN', visitors: 83, percentage: 7 },
230
+ { name: 'Indonesian', code: 'id-ID', visitors: 80, percentage: 7 },
231
+ { name: 'French', code: 'fr-FR', visitors: 62, percentage: 5 },
232
+ { name: 'Portuguese', code: 'pt-BR', visitors: 58, percentage: 5 },
233
+ { name: 'Japanese', code: 'ja-JP', visitors: 52, percentage: 4 },
234
+ { name: 'Dutch', code: 'nl-NL', visitors: 45, percentage: 4 },
235
+ { name: 'Spanish', code: 'es-ES', visitors: 42, percentage: 3 },
236
+ ])
237
+
238
+ let chartHandle: { destroy: () => void } | null = null
239
+
240
+ onMount(async () => {
241
+ const { Chart, registerables } = await import('@stacksjs/charts')
242
+ Chart.register(...registerables)
243
+ const Ctor = Chart as unknown as ChartCtor
244
+
245
+ const top = countriesData().slice(0, 10)
246
+ const total = countriesData().reduce((a, b) => a + b.visitors, 0)
247
+
248
+ chartHandle = useChart({
249
+ Chart: Ctor,
250
+ id: 'countryChart',
251
+ type: 'bar',
252
+ data: {
253
+ labels: top.map(item => item.name),
254
+ datasets: [{
255
+ label: 'Visitors',
256
+ data: top.map(item => item.visitors),
257
+ backgroundColor: ['rgba(59, 130, 246, 0.8)', 'rgba(16, 185, 129, 0.8)', 'rgba(245, 158, 11, 0.8)', 'rgba(239, 68, 68, 0.8)', 'rgba(139, 92, 246, 0.8)', 'rgba(236, 72, 153, 0.8)', 'rgba(14, 165, 233, 0.8)', 'rgba(168, 85, 247, 0.8)', 'rgba(249, 115, 22, 0.8)', 'rgba(234, 179, 8, 0.8)'],
258
+ borderColor: 'rgba(255, 255, 255, 0.8)',
259
+ borderWidth: 1,
260
+ }],
261
+ },
262
+ options: {
263
+ indexAxis: 'y',
264
+ responsive: true,
265
+ maintainAspectRatio: false,
266
+ plugins: {
267
+ legend: { display: false },
268
+ tooltip: {
269
+ callbacks: {
270
+ label(context: { raw?: number }) {
271
+ const value = context.raw || 0
272
+ const percentage = Math.round((value / total) * 100)
273
+ return `${value} visitors (${percentage}%)`
274
+ },
275
+ },
276
+ },
277
+ },
278
+ scales: { x: { beginAtZero: true, grid: { display: false } }, y: { grid: { display: false } } },
279
+ },
280
+ })
281
+ })
282
+
283
+ onDestroy(() => {
284
+ chartHandle?.destroy()
285
+ chartHandle = null
286
+ })
287
+ </script>
288
+
289
+ @endsection
@@ -0,0 +1,305 @@
1
+ @extends('layouts/default')
2
+
3
+ @section('content')
4
+ @title('Dashboard - Device Analytics')
5
+ <PageLayout>
6
+ <div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between mb-6">
7
+ <div class="flex items-center space-x-2">
8
+ <div class="h-5 w-5 text-gray-500 dark:text-neutral-400 i-hugeicons-calendar-03"></div>
9
+ <span class="font-medium text-gray-700 text-sm dark:text-neutral-300">{{ dateRangeDisplay }}</span>
10
+ </div>
11
+
12
+ <div class="flex flex-wrap gap-2 items-center">
13
+ <span class="text-gray-500 text-sm dark:text-neutral-400">compared to</span>
14
+ <div class="relative">
15
+ <select x-model="comparisonType" class="block pl-3 pr-10 py-1.5 w-full text-gray-900 sm:leading-6 sm:text-sm dark:text-white dark:bg-neutral-800 border-0 ring-1 ring-gray-300 ring-inset rounded-md dark:ring-neutral-700 focus:ring-2 focus:ring-blue-600 focus:ring-inset">
16
+ <option value="no-comparison">No comparison</option>
17
+ <option value="previous-period">Previous period</option>
18
+ <option value="previous-year">Previous year</option>
19
+ </select>
20
+ </div>
21
+ <button type="button" class="inline-flex items-center px-3 py-1.5 font-semibold text-gray-900 text-sm dark:text-white bg-white dark:bg-neutral-700 hover:bg-gray-50 dark:hover:bg-neutral-600 ring-1 ring-gray-300 ring-inset rounded-md dark:ring-neutral-600 shadow-sm">
22
+ <div class="mr-1 h-4 w-4 i-hugeicons-settings-01"></div>
23
+ Auto
24
+ </button>
25
+ </div>
26
+ </div>
27
+
28
+ <div class="mb-8">
29
+ <h1 class="font-bold text-2xl text-gray-900 dark:text-white">Device Analytics</h1>
30
+ <p class="mt-1 text-gray-500 text-sm dark:text-neutral-400">Detailed breakdown of device usage across your website</p>
31
+ </div>
32
+
33
+ <div class="grid gap-8 grid-cols-1 lg:grid-cols-2 mb-8">
34
+ <div class="p-4 bg-white dark:bg-neutral-800 rounded-lg shadow">
35
+ <div class="mb-4">
36
+ <h3 class="font-medium leading-6 text-gray-900 text-lg dark:text-white">Device Distribution</h3>
37
+ <p class="mt-1 text-gray-500 text-sm dark:text-neutral-400">Percentage of visitors by device type</p>
38
+ </div>
39
+ <div class="h-80 w-full">
40
+ <canvas id="deviceDistributionChart"></canvas>
41
+ </div>
42
+ </div>
43
+
44
+ <div class="p-4 bg-white dark:bg-neutral-800 rounded-lg shadow">
45
+ <div class="mb-4">
46
+ <h3 class="font-medium leading-6 text-gray-900 text-lg dark:text-white">Device Trends</h3>
47
+ <p class="mt-1 text-gray-500 text-sm dark:text-neutral-400">Device usage trends over time</p>
48
+ </div>
49
+ <div class="h-80 w-full">
50
+ <canvas id="deviceTrendChart"></canvas>
51
+ </div>
52
+ </div>
53
+ </div>
54
+
55
+ <div class="mb-8">
56
+ <div class="mb-4">
57
+ <h3 class="font-medium text-gray-900 text-lg dark:text-white">Device Overview</h3>
58
+ </div>
59
+
60
+ <div class="overflow-hidden border border-gray-200 rounded-lg dark:border-neutral-700">
61
+ <table class="min-w-full divide-gray-200 divide-y dark:divide-neutral-700">
62
+ <thead class="bg-gray-50 dark:bg-neutral-700/50">
63
+ <tr>
64
+ <th scope="col" class="px-4 py-3 font-medium text-gray-500 text-left text-xs tracking-wider uppercase dark:text-neutral-300">Device Type</th>
65
+ <th scope="col" class="px-4 py-3 font-medium text-gray-500 text-right text-xs tracking-wider uppercase dark:text-neutral-300">Visitors</th>
66
+ <th scope="col" class="px-4 py-3 font-medium text-gray-500 text-right text-xs tracking-wider uppercase dark:text-neutral-300">%</th>
67
+ </tr>
68
+ </thead>
69
+ <tbody class="bg-white dark:bg-neutral-800 divide-gray-200 divide-y dark:divide-neutral-700">
70
+ <template :for="(device, index) in deviceData">
71
+ <tr class="relative hover:bg-gray-50 dark:hover:bg-neutral-700/50">
72
+ <td class="px-4 py-3 text-gray-900 text-sm whitespace-nowrap dark:text-white">
73
+ <div class="absolute inset-0 bg-purple-100/50 dark:bg-purple-900/50" style="width: {{ device.percentage }}%"></div>
74
+ <span class="relative z-10">{{ device.name }}</span>
75
+ </td>
76
+ <td class="relative px-4 py-3 text-gray-500 text-right text-sm whitespace-nowrap dark:text-neutral-300">
77
+ <span class="relative z-10">{{ device.visitors }}</span>
78
+ </td>
79
+ <td class="relative px-4 py-3 text-gray-500 text-right text-sm whitespace-nowrap dark:text-neutral-300">
80
+ <span class="relative z-10">{{ device.percentage }}%</span>
81
+ </td>
82
+ </tr>
83
+ </template>
84
+ </tbody>
85
+ </table>
86
+ </div>
87
+ </div>
88
+
89
+ <div class="mb-8">
90
+ <div class="mb-4">
91
+ <h3 class="font-medium text-gray-900 text-lg dark:text-white">Detailed Device Data</h3>
92
+ <p class="mt-1 text-gray-500 text-sm dark:text-neutral-400">Device usage by model and operating system</p>
93
+ </div>
94
+
95
+ <div class="overflow-hidden border border-gray-200 rounded-lg dark:border-neutral-700">
96
+ <table class="min-w-full divide-gray-200 divide-y dark:divide-neutral-700">
97
+ <thead class="bg-gray-50 dark:bg-neutral-700/50">
98
+ <tr>
99
+ <th scope="col" class="px-4 py-3 font-medium text-gray-500 text-left text-xs tracking-wider uppercase dark:text-neutral-300">Device Type</th>
100
+ <th scope="col" class="px-4 py-3 font-medium text-gray-500 text-left text-xs tracking-wider uppercase dark:text-neutral-300">Model</th>
101
+ <th scope="col" class="px-4 py-3 font-medium text-gray-500 text-left text-xs tracking-wider uppercase dark:text-neutral-300">OS</th>
102
+ <th scope="col" class="px-4 py-3 font-medium text-gray-500 text-right text-xs tracking-wider uppercase dark:text-neutral-300">Visitors</th>
103
+ <th scope="col" class="px-4 py-3 font-medium text-gray-500 text-right text-xs tracking-wider uppercase dark:text-neutral-300">%</th>
104
+ </tr>
105
+ </thead>
106
+ <tbody class="bg-white dark:bg-neutral-800 divide-gray-200 divide-y dark:divide-neutral-700">
107
+ <template :for="(device, index) in detailedDeviceData">
108
+ <tr class="relative hover:bg-gray-50 dark:hover:bg-neutral-700/50">
109
+ <td class="px-4 py-3 text-gray-900 text-sm whitespace-nowrap dark:text-white">
110
+ <div class="absolute inset-0 bg-purple-100/50 dark:bg-purple-900/50" style="width: {{ device.percentage }}%"></div>
111
+ <span class="relative z-10">{{ device.name }}</span>
112
+ </td>
113
+ <td class="relative px-4 py-3 text-gray-900 text-sm whitespace-nowrap dark:text-white">
114
+ <span class="relative z-10">{{ device.model }}</span>
115
+ </td>
116
+ <td class="relative px-4 py-3 text-gray-900 text-sm whitespace-nowrap dark:text-white">
117
+ <span class="relative z-10">{{ device.os }}</span>
118
+ </td>
119
+ <td class="relative px-4 py-3 text-gray-500 text-right text-sm whitespace-nowrap dark:text-neutral-300">
120
+ <span class="relative z-10">{{ device.visitors }}</span>
121
+ </td>
122
+ <td class="relative px-4 py-3 text-gray-500 text-right text-sm whitespace-nowrap dark:text-neutral-300">
123
+ <span class="relative z-10">{{ device.percentage }}%</span>
124
+ </td>
125
+ </tr>
126
+ </template>
127
+ </tbody>
128
+ </table>
129
+ </div>
130
+ </div>
131
+
132
+ <div>
133
+ <div class="mb-4">
134
+ <h3 class="font-medium text-gray-900 text-lg dark:text-white">Screen Sizes</h3>
135
+ <p class="mt-1 text-gray-500 text-sm dark:text-neutral-400">Visitor screen resolution breakdown</p>
136
+ </div>
137
+
138
+ <div class="overflow-hidden border border-gray-200 rounded-lg dark:border-neutral-700">
139
+ <table class="min-w-full divide-gray-200 divide-y dark:divide-neutral-700">
140
+ <thead class="bg-gray-50 dark:bg-neutral-700/50">
141
+ <tr>
142
+ <th scope="col" class="px-4 py-3 font-medium text-gray-500 text-left text-xs tracking-wider uppercase dark:text-neutral-300">Screen Resolution</th>
143
+ <th scope="col" class="px-4 py-3 font-medium text-gray-500 text-right text-xs tracking-wider uppercase dark:text-neutral-300">Visitors</th>
144
+ <th scope="col" class="px-4 py-3 font-medium text-gray-500 text-right text-xs tracking-wider uppercase dark:text-neutral-300">%</th>
145
+ </tr>
146
+ </thead>
147
+ <tbody class="bg-white dark:bg-neutral-800 divide-gray-200 divide-y dark:divide-neutral-700">
148
+ <template :for="(screen, index) in screenSizeData">
149
+ <tr class="relative hover:bg-gray-50 dark:hover:bg-neutral-700/50">
150
+ <td class="px-4 py-3 text-gray-900 text-sm whitespace-nowrap dark:text-white">
151
+ <div class="absolute inset-0 bg-indigo-100/50 dark:bg-indigo-900/50" style="width: {{ screen.percentage }}%"></div>
152
+ <span class="relative z-10">{{ screen.size }}</span>
153
+ </td>
154
+ <td class="relative px-4 py-3 text-gray-500 text-right text-sm whitespace-nowrap dark:text-neutral-300">
155
+ <span class="relative z-10">{{ screen.visitors }}</span>
156
+ </td>
157
+ <td class="relative px-4 py-3 text-gray-500 text-right text-sm whitespace-nowrap dark:text-neutral-300">
158
+ <span class="relative z-10">{{ screen.percentage }}%</span>
159
+ </td>
160
+ </tr>
161
+ </template>
162
+ </tbody>
163
+ </table>
164
+ </div>
165
+ </div>
166
+ </PageLayout>
167
+ <script client>
168
+
169
+ interface DeviceRow {
170
+ name: string
171
+ visitors: number
172
+ percentage: number
173
+ model?: string
174
+ os?: string
175
+ }
176
+
177
+ interface ScreenSizeRow {
178
+ size: string
179
+ visitors: number
180
+ percentage: number
181
+ }
182
+
183
+ interface ChartLike { destroy: () => void }
184
+ type ChartCtor = new (canvas: HTMLElement, config: { type: string, data: unknown, options?: unknown }) => ChartLike
185
+
186
+ const dateRangeDisplay = state('All Time: Sep 7, 2023 to Mar 6, 2025')
187
+ const comparisonType = state('no-comparison')
188
+
189
+ const deviceData = state<DeviceRow[]>([
190
+ { name: 'Desktop', visitors: 1300, percentage: 60 },
191
+ { name: 'Phone', visitors: 874, percentage: 38 },
192
+ { name: 'Tablet', visitors: 5, percentage: 2 },
193
+ ])
194
+
195
+ const detailedDeviceData = state<DeviceRow[]>([
196
+ { name: 'Desktop', model: 'Windows PC', os: 'Windows 11', visitors: 450, percentage: 20 },
197
+ { name: 'Desktop', model: 'Windows PC', os: 'Windows 10', visitors: 380, percentage: 17 },
198
+ { name: 'Desktop', model: 'Mac', os: 'macOS 14', visitors: 250, percentage: 11 },
199
+ { name: 'Desktop', model: 'Mac', os: 'macOS 13', visitors: 150, percentage: 7 },
200
+ { name: 'Desktop', model: 'Linux PC', os: 'Ubuntu', visitors: 70, percentage: 3 },
201
+ { name: 'Phone', model: 'iPhone', os: 'iOS 17', visitors: 320, percentage: 14 },
202
+ { name: 'Phone', model: 'iPhone', os: 'iOS 16', visitors: 180, percentage: 8 },
203
+ { name: 'Phone', model: 'Samsung Galaxy', os: 'Android 14', visitors: 150, percentage: 7 },
204
+ { name: 'Phone', model: 'Google Pixel', os: 'Android 14', visitors: 89, percentage: 4 },
205
+ { name: 'Phone', model: 'Xiaomi', os: 'Android 13', visitors: 135, percentage: 6 },
206
+ { name: 'Tablet', model: 'iPad', os: 'iPadOS 17', visitors: 3, percentage: 0.1 },
207
+ { name: 'Tablet', model: 'Samsung Tab', os: 'Android 14', visitors: 2, percentage: 0.1 },
208
+ ])
209
+
210
+ const deviceTrendData = state<Array<{ date: string, Desktop: number, Phone: number, Tablet: number }>>([
211
+ { date: '2023-09', Desktop: 800, Phone: 400, Tablet: 10 },
212
+ { date: '2023-10', Desktop: 850, Phone: 420, Tablet: 9 },
213
+ { date: '2023-11', Desktop: 900, Phone: 450, Tablet: 8 },
214
+ { date: '2023-12', Desktop: 950, Phone: 480, Tablet: 7 },
215
+ { date: '2024-01', Desktop: 1000, Phone: 500, Tablet: 6 },
216
+ { date: '2024-02', Desktop: 1100, Phone: 600, Tablet: 5 },
217
+ { date: '2024-03', Desktop: 1200, Phone: 700, Tablet: 5 },
218
+ { date: '2024-04', Desktop: 1250, Phone: 750, Tablet: 5 },
219
+ { date: '2024-05', Desktop: 1300, Phone: 874, Tablet: 5 },
220
+ ])
221
+
222
+ const screenSizeData = state<ScreenSizeRow[]>([
223
+ { size: '1920x1080', visitors: 580, percentage: 26 },
224
+ { size: '1366x768', visitors: 450, percentage: 20 },
225
+ { size: '1440x900', visitors: 320, percentage: 14 },
226
+ { size: '375x812', visitors: 280, percentage: 13 },
227
+ { size: '414x896', visitors: 220, percentage: 10 },
228
+ { size: '360x740', visitors: 180, percentage: 8 },
229
+ { size: '1536x864', visitors: 120, percentage: 5 },
230
+ { size: '768x1024', visitors: 80, percentage: 4 },
231
+ ])
232
+
233
+ let chartHandles: Array<{ destroy: () => void }> = []
234
+
235
+ onMount(async () => {
236
+ const { Chart, registerables } = await import('@stacksjs/charts')
237
+ Chart.register(...registerables)
238
+ const Ctor = Chart as unknown as ChartCtor
239
+
240
+ const distribution = useChart({
241
+ Chart: Ctor,
242
+ id: 'deviceDistributionChart',
243
+ type: 'doughnut',
244
+ data: {
245
+ labels: deviceData().map(item => item.name),
246
+ datasets: [{
247
+ data: deviceData().map(item => item.visitors),
248
+ backgroundColor: ['rgba(59, 130, 246, 0.8)', 'rgba(16, 185, 129, 0.8)', 'rgba(245, 158, 11, 0.8)'],
249
+ borderColor: 'rgba(255, 255, 255, 0.8)',
250
+ borderWidth: 1,
251
+ }],
252
+ },
253
+ options: {
254
+ responsive: true,
255
+ maintainAspectRatio: false,
256
+ plugins: {
257
+ legend: { position: 'right', labels: { padding: 20, font: { size: 12 } } },
258
+ tooltip: {
259
+ callbacks: {
260
+ label(context: { label?: string, raw?: number, dataset: { data: number[] } }) {
261
+ const label = context.label || ''
262
+ const value = context.raw || 0
263
+ const total = context.dataset.data.reduce((a: number, b: number) => a + b, 0)
264
+ const percentage = Math.round((value / total) * 100)
265
+ return `${label}: ${value} visitors (${percentage}%)`
266
+ },
267
+ },
268
+ },
269
+ },
270
+ },
271
+ })
272
+
273
+ const trend = useChart({
274
+ Chart: Ctor,
275
+ id: 'deviceTrendChart',
276
+ type: 'line',
277
+ data: {
278
+ labels: deviceTrendData().map(item => item.date),
279
+ datasets: [
280
+ { label: 'Desktop', data: deviceTrendData().map(item => item.Desktop), borderColor: 'rgba(59, 130, 246, 0.8)', backgroundColor: 'rgba(59, 130, 246, 0.1)', tension: 0.4, fill: false },
281
+ { label: 'Phone', data: deviceTrendData().map(item => item.Phone), borderColor: 'rgba(16, 185, 129, 0.8)', backgroundColor: 'rgba(16, 185, 129, 0.1)', tension: 0.4, fill: false },
282
+ { label: 'Tablet', data: deviceTrendData().map(item => item.Tablet), borderColor: 'rgba(245, 158, 11, 0.8)', backgroundColor: 'rgba(245, 158, 11, 0.1)', tension: 0.4, fill: false },
283
+ ],
284
+ },
285
+ options: {
286
+ responsive: true,
287
+ maintainAspectRatio: false,
288
+ scales: {
289
+ x: { grid: { display: false } },
290
+ y: { beginAtZero: true, grid: { borderDash: [2, 4], color: 'rgba(160, 174, 192, 0.2)' }, ticks: { maxTicksLimit: 6 } },
291
+ },
292
+ plugins: { legend: { position: 'top' }, tooltip: { mode: 'index', intersect: false } },
293
+ },
294
+ })
295
+
296
+ chartHandles = [distribution.instance, trend.instance].filter((c): c is ChartLike => c !== null)
297
+ })
298
+
299
+ onDestroy(() => {
300
+ chartHandles.forEach(c => c.destroy())
301
+ chartHandles = []
302
+ })
303
+ </script>
304
+
305
+ @endsection