@awes-io/ui 2.142.0 → 2.143.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (239) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/assets/css/components/_index.css +7 -1
  3. package/assets/css/components/animation.css +38 -32
  4. package/assets/css/components/content-placeholder.css +103 -0
  5. package/assets/css/components/empty-container.css +69 -1
  6. package/assets/css/components/filter-chosen.css +6 -0
  7. package/assets/css/components/filter-date-range.css +17 -1
  8. package/assets/css/components/filter-month.css +23 -17
  9. package/assets/css/components/filter-select.css +11 -0
  10. package/assets/css/components/layout.css +1 -32
  11. package/assets/css/components/modal.css +1 -1
  12. package/assets/css/components/number.css +12 -0
  13. package/assets/css/components/page-aside.css +54 -0
  14. package/assets/js/css.js +1 -1
  15. package/assets/js/icons/mono.js +59 -91
  16. package/assets/js/icons/multicolor.js +1 -31
  17. package/components/1_atoms/AwContentPlaceholder.vue +60 -0
  18. package/components/1_atoms/AwFlow.vue +21 -48
  19. package/components/1_atoms/AwLabel.vue +1 -1
  20. package/components/2_molecules/AwButton.vue +1 -1
  21. package/components/2_molecules/AwEmptyContainer.vue +74 -72
  22. package/components/2_molecules/AwNumber.vue +180 -0
  23. package/components/2_molecules/AwSelect.vue +11 -4
  24. package/components/3_organisms/AwFilterChosen.vue +73 -0
  25. package/components/3_organisms/AwFilterDateRange.vue +177 -0
  26. package/components/3_organisms/AwFilterMonth.vue +37 -40
  27. package/components/3_organisms/AwFilterSelect.vue +368 -0
  28. package/components/3_organisms/AwImageUpload.vue +1 -1
  29. package/components/3_organisms/AwMarkdownEditor.vue +0 -0
  30. package/components/3_organisms/AwMultiBlockBuilder.vue +1 -1
  31. package/components/3_organisms/AwTable/AwTableBuilder.vue +12 -60
  32. package/components/4_pages/AwPageAside.vue +108 -0
  33. package/components/5_layouts/AwLayoutCenter.vue +3 -8
  34. package/components/5_layouts/_AwUserMenu.vue +1 -1
  35. package/dist/css/aw-icons.css +26 -0
  36. package/dist/fonts/aw-icons.svg +18 -0
  37. package/dist/fonts/aw-icons.ttf +0 -0
  38. package/dist/fonts/aw-icons.woff +0 -0
  39. package/dist/fonts/aw-icons.woff2 +0 -0
  40. package/docs/_template.md +80 -0
  41. package/docs/components/atoms/aw-accordion-fold.md +91 -0
  42. package/docs/components/atoms/aw-action-card-body.md +67 -0
  43. package/docs/components/atoms/aw-action-card.md +94 -0
  44. package/docs/components/atoms/aw-action-icon.md +88 -0
  45. package/docs/components/atoms/aw-avatar.md +106 -0
  46. package/docs/components/atoms/aw-card.md +112 -0
  47. package/docs/components/atoms/aw-checkbox.md +112 -0
  48. package/docs/components/atoms/aw-content-placeholder.md +116 -0
  49. package/docs/components/atoms/aw-description.md +83 -0
  50. package/docs/components/atoms/aw-dock.md +84 -0
  51. package/docs/components/atoms/aw-dropdown-button.md +94 -0
  52. package/docs/components/atoms/aw-dropdown.md +128 -0
  53. package/docs/components/atoms/aw-file.md +73 -0
  54. package/docs/components/atoms/aw-flow.md +92 -0
  55. package/docs/components/atoms/aw-grid.md +91 -0
  56. package/docs/components/atoms/aw-headline.md +71 -0
  57. package/docs/components/atoms/aw-icon-system-color.md +121 -0
  58. package/docs/components/atoms/aw-icon-system-mono.md +205 -0
  59. package/docs/components/atoms/aw-icon.md +235 -0
  60. package/docs/components/atoms/aw-info.md +85 -0
  61. package/docs/components/atoms/aw-input.md +120 -0
  62. package/docs/components/atoms/aw-label.md +83 -0
  63. package/docs/components/atoms/aw-link.md +99 -0
  64. package/docs/components/atoms/aw-list.md +88 -0
  65. package/docs/components/atoms/aw-progress.md +70 -0
  66. package/docs/components/atoms/aw-radio.md +109 -0
  67. package/docs/components/atoms/aw-refresh-wrapper.md +81 -0
  68. package/docs/components/atoms/aw-select-native.md +106 -0
  69. package/docs/components/atoms/aw-slider.md +82 -0
  70. package/docs/components/atoms/aw-sub-headline.md +73 -0
  71. package/docs/components/atoms/aw-switcher.md +115 -0
  72. package/docs/components/atoms/aw-tag.md +80 -0
  73. package/docs/components/atoms/aw-title.md +70 -0
  74. package/docs/components/atoms/aw-toggler.md +69 -0
  75. package/docs/components/layouts/aw-layout-center.md +168 -0
  76. package/docs/components/layouts/aw-layout-error.md +153 -0
  77. package/docs/components/layouts/aw-layout-provider.md +238 -0
  78. package/docs/components/layouts/aw-layout.md +88 -0
  79. package/docs/components/molecules/aw-action-button.md +91 -0
  80. package/docs/components/molecules/aw-alert.md +96 -0
  81. package/docs/components/molecules/aw-badge.md +108 -0
  82. package/docs/components/molecules/aw-banner-text.md +90 -0
  83. package/docs/components/molecules/aw-button-nav.md +46 -0
  84. package/docs/components/molecules/aw-button.md +123 -0
  85. package/docs/components/molecules/aw-description-input.md +67 -0
  86. package/docs/components/molecules/aw-empty-container.md +86 -0
  87. package/docs/components/molecules/aw-island.md +234 -0
  88. package/docs/components/molecules/aw-number.md +138 -0
  89. package/docs/components/molecules/aw-select-object.md +401 -0
  90. package/docs/components/molecules/aw-select.md +215 -0
  91. package/docs/components/molecules/aw-tab-nav.md +108 -0
  92. package/docs/components/molecules/aw-tel.md +129 -0
  93. package/docs/components/molecules/aw-textarea.md +83 -0
  94. package/docs/components/molecules/aw-userpic.md +115 -0
  95. package/docs/components/organisms/aw-address-block.md +64 -0
  96. package/docs/components/organisms/aw-address.md +132 -0
  97. package/docs/components/organisms/aw-birthday-picker.md +73 -0
  98. package/docs/components/organisms/aw-bottom-bar.md +66 -0
  99. package/docs/components/organisms/aw-calendar-days.md +115 -0
  100. package/docs/components/organisms/aw-calendar-nav.md +98 -0
  101. package/docs/components/organisms/aw-calendar-view.md +98 -0
  102. package/docs/components/organisms/aw-calendar.md +166 -0
  103. package/docs/components/organisms/aw-chart.md +154 -0
  104. package/docs/components/organisms/aw-chip-select.md +164 -0
  105. package/docs/components/organisms/aw-chip.md +126 -0
  106. package/docs/components/organisms/aw-code-snippet.md +94 -0
  107. package/docs/components/organisms/aw-code.md +132 -0
  108. package/docs/components/organisms/aw-context-menu.md +117 -0
  109. package/docs/components/organisms/aw-cropper.md +151 -0
  110. package/docs/components/organisms/aw-date.md +161 -0
  111. package/docs/components/organisms/aw-display-date.md +33 -0
  112. package/docs/components/organisms/aw-download-link.md +46 -0
  113. package/docs/components/organisms/aw-fetch-data.md +161 -0
  114. package/docs/components/organisms/aw-filter-chosen.md +226 -0
  115. package/docs/components/organisms/aw-filter-date-range.md +205 -0
  116. package/docs/components/organisms/aw-filter-month.md +43 -0
  117. package/docs/components/organisms/aw-filter-select.md +225 -0
  118. package/docs/components/organisms/aw-form.md +174 -0
  119. package/docs/components/organisms/aw-gmap-marker.md +86 -0
  120. package/docs/components/organisms/aw-gmap.md +90 -0
  121. package/docs/components/organisms/aw-image-upload.md +56 -0
  122. package/docs/components/organisms/aw-island-avatar.md +87 -0
  123. package/docs/components/organisms/aw-markdown-editor.md +104 -0
  124. package/docs/components/organisms/aw-modal-buttons.md +57 -0
  125. package/docs/components/organisms/aw-modal.md +246 -0
  126. package/docs/components/organisms/aw-model-edit.md +74 -0
  127. package/docs/components/organisms/aw-money.md +53 -0
  128. package/docs/components/organisms/aw-multi-block-builder.md +165 -0
  129. package/docs/components/organisms/aw-pagination.md +121 -0
  130. package/docs/components/organisms/aw-password.md +103 -0
  131. package/docs/components/organisms/aw-preview-card.md +45 -0
  132. package/docs/components/organisms/aw-search.md +116 -0
  133. package/docs/components/organisms/aw-subnav.md +122 -0
  134. package/docs/components/organisms/aw-table-builder.md +165 -0
  135. package/docs/components/organisms/aw-table-col.md +123 -0
  136. package/docs/components/organisms/aw-table-head.md +92 -0
  137. package/docs/components/organisms/aw-table-row.md +91 -0
  138. package/docs/components/organisms/aw-table.md +172 -0
  139. package/docs/components/organisms/aw-tags.md +54 -0
  140. package/docs/components/organisms/aw-toggle-show-aside.md +43 -0
  141. package/docs/components/organisms/aw-uploader-files.md +125 -0
  142. package/docs/components/organisms/aw-uploader.md +163 -0
  143. package/docs/components/organisms/aw-user-menu.md +87 -0
  144. package/docs/components/pages/aw-page-aside.md +296 -0
  145. package/docs/components/pages/aw-page-menu-buttons.md +172 -0
  146. package/docs/components/pages/aw-page-modal.md +198 -0
  147. package/docs/components/pages/aw-page-single.md +253 -0
  148. package/docs/components/pages/aw-page.md +194 -0
  149. package/docs/configuration.md +493 -0
  150. package/docs/cookbook/advanced-patterns.md +1388 -0
  151. package/docs/cookbook/common-patterns.md +965 -0
  152. package/docs/cookbook/index.md +786 -0
  153. package/docs/getting-started.md +596 -0
  154. package/docs/guides/best-practices.md +1106 -0
  155. package/docs/guides/data-fetching.md +852 -0
  156. package/docs/guides/error-handling.md +1172 -0
  157. package/docs/guides/forms-guide.md +1329 -0
  158. package/docs/guides/mobile-subnavigation.md +359 -0
  159. package/docs/guides/page-patterns/aside-pages.md +1418 -0
  160. package/docs/guides/page-patterns/dashboard-pages.md +990 -0
  161. package/docs/guides/page-patterns/detail-pages.md +1493 -0
  162. package/docs/guides/page-patterns/list-pages.md +1094 -0
  163. package/docs/index.md +263 -1
  164. package/docs/integrations.md +870 -0
  165. package/docs/reference/menu.md +462 -0
  166. package/docs/reference/plugins.md +970 -0
  167. package/docs/reference/troubleshooting.md +945 -0
  168. package/nuxt/awes.config.js +9 -8
  169. package/nuxt/icons.css +26 -0
  170. package/nuxt/index.js +2 -2
  171. package/nuxt/pages/more.vue +1 -1
  172. package/package.json +5 -3
  173. package/readme.md +171 -1
  174. package/docs/aw-accordion-fold.md +0 -46
  175. package/docs/aw-address.md +0 -44
  176. package/docs/aw-avatar.md +0 -51
  177. package/docs/aw-badge.md +0 -32
  178. package/docs/aw-button-nav.md +0 -44
  179. package/docs/aw-button.md +0 -50
  180. package/docs/aw-calendar-days.md +0 -46
  181. package/docs/aw-calendar-nav.md +0 -25
  182. package/docs/aw-calendar-view.md +0 -12
  183. package/docs/aw-calendar.md +0 -59
  184. package/docs/aw-card.md +0 -48
  185. package/docs/aw-chart.md +0 -51
  186. package/docs/aw-checkbox.md +0 -56
  187. package/docs/aw-chip-select.md +0 -46
  188. package/docs/aw-chip.md +0 -53
  189. package/docs/aw-code-snippet.md +0 -18
  190. package/docs/aw-code.md +0 -56
  191. package/docs/aw-content-wrapper.md +0 -40
  192. package/docs/aw-context-menu.md +0 -31
  193. package/docs/aw-cropper.md +0 -60
  194. package/docs/aw-dashboard-card.md +0 -37
  195. package/docs/aw-dashboard-donut.md +0 -30
  196. package/docs/aw-dashboard-line.md +0 -20
  197. package/docs/aw-dashboard-progress.md +0 -33
  198. package/docs/aw-dashboard-section.md +0 -32
  199. package/docs/aw-dashboard-speed.md +0 -30
  200. package/docs/aw-date.md +0 -52
  201. package/docs/aw-dropdown-button.md +0 -31
  202. package/docs/aw-dropdown.md +0 -69
  203. package/docs/aw-fetch-data.md +0 -45
  204. package/docs/aw-form.md +0 -52
  205. package/docs/aw-grid.md +0 -48
  206. package/docs/aw-icon.md +0 -50
  207. package/docs/aw-info.md +0 -53
  208. package/docs/aw-input.md +0 -55
  209. package/docs/aw-layout-default.md +0 -30
  210. package/docs/aw-layout-frame-center.md +0 -29
  211. package/docs/aw-layout-simple.md +0 -49
  212. package/docs/aw-link.md +0 -54
  213. package/docs/aw-markdown-editor.md +0 -51
  214. package/docs/aw-modal.md +0 -63
  215. package/docs/aw-multi-block-builder.md +0 -66
  216. package/docs/aw-page.md +0 -36
  217. package/docs/aw-pagination.md +0 -54
  218. package/docs/aw-password.md +0 -48
  219. package/docs/aw-radio.md +0 -54
  220. package/docs/aw-search.md +0 -49
  221. package/docs/aw-select.md +0 -93
  222. package/docs/aw-slider.md +0 -40
  223. package/docs/aw-svg-image.md +0 -19
  224. package/docs/aw-switcher.md +0 -51
  225. package/docs/aw-tab-nav.md +0 -55
  226. package/docs/aw-table-builder.md +0 -58
  227. package/docs/aw-table-col.md +0 -33
  228. package/docs/aw-table-head.md +0 -28
  229. package/docs/aw-table-row.md +0 -33
  230. package/docs/aw-table.md +0 -59
  231. package/docs/aw-tel.md +0 -47
  232. package/docs/aw-textarea.md +0 -47
  233. package/docs/aw-timeline-builder.md +0 -50
  234. package/docs/aw-toggler.md +0 -41
  235. package/docs/aw-uploader-files.md +0 -20
  236. package/docs/aw-uploader.md +0 -60
  237. package/docs/aw-user-menu.md +0 -34
  238. package/docs/aw-userpic.md +0 -34
  239. /package/components/{3_organisms → 2_molecules}/AwTel.vue +0 -0
@@ -0,0 +1,970 @@
1
+ # Plugins & Utilities Reference
2
+
3
+ Complete reference for all AwesCode UI plugins and utility methods available in your application.
4
+
5
+ ## Overview
6
+
7
+ AwesCode UI provides several plugins that extend Nuxt with custom functionality:
8
+
9
+ | Plugin | Purpose | Available As |
10
+ |--------|---------|--------------|
11
+ | **core** | Notifications, config access | `$notify`, `$confirm`, `$awes` |
12
+ | **screen** | Responsive breakpoints | `$screen` |
13
+ | **dayjs** | Date formatting | `$dayjs` |
14
+ | **router** | Router extensions | `router.pushBack`, `router.setBack` |
15
+ | **dark-theme** | Theme management | `$store.commit('awesIo/SET_DARK_THEME')`, `$store.getters['awesIo/isDarkTheme']` |
16
+ | **permissions** | CASL permissions | `$can`, `$cannot` |
17
+
18
+ All plugins are automatically registered by the `@awes-io/ui` Nuxt module.
19
+
20
+ ## $notify
21
+
22
+ Display toast notifications to users.
23
+
24
+ ### Basic Usage
25
+
26
+ ```javascript
27
+ // Success notification
28
+ this.$notify({
29
+ title: 'Customer saved successfully',
30
+ type: 'success'
31
+ })
32
+
33
+ // Error notification
34
+ this.$notify({
35
+ title: 'Failed to load data',
36
+ type: 'error'
37
+ })
38
+
39
+ // Warning notification
40
+ this.$notify({
41
+ title: 'Data may be outdated',
42
+ type: 'warning'
43
+ })
44
+
45
+ // Info notification
46
+ this.$notify({
47
+ title: 'Processing request...',
48
+ type: 'info'
49
+ })
50
+ ```
51
+
52
+ ### Notification Types
53
+
54
+ ```javascript
55
+ // Success (green)
56
+ this.$notify({
57
+ title: 'Operation completed',
58
+ type: 'success'
59
+ })
60
+
61
+ // Error (red)
62
+ this.$notify({
63
+ title: 'Something went wrong',
64
+ type: 'error'
65
+ })
66
+
67
+ // Warning (yellow/orange)
68
+ this.$notify({
69
+ title: 'Please review your input',
70
+ type: 'warning'
71
+ })
72
+
73
+ // Info (blue)
74
+ this.$notify({
75
+ title: 'Your session will expire in 5 minutes',
76
+ type: 'info'
77
+ })
78
+ ```
79
+
80
+ ### With Duration
81
+
82
+ ```javascript
83
+ // Auto-dismiss after 5 seconds (default)
84
+ this.$notify({
85
+ title: 'Auto-dismiss notification'
86
+ })
87
+
88
+ // Auto-dismiss after 10 seconds
89
+ this.$notify({
90
+ title: 'Longer notification',
91
+ timeout: 10000
92
+ })
93
+
94
+ // Never auto-dismiss (requires manual close)
95
+ this.$notify({
96
+ title: 'Important: Please read carefully',
97
+ timeout: 0
98
+ })
99
+ ```
100
+
101
+ ### With Title
102
+
103
+ ```javascript
104
+ this.$notify({
105
+ title: 'Success',
106
+ text: 'Customer profile updated successfully',
107
+ type: 'success'
108
+ })
109
+
110
+ this.$notify({
111
+ title: 'Error',
112
+ text: 'Unable to connect to server',
113
+ type: 'error'
114
+ })
115
+ ```
116
+
117
+ ### Common Patterns
118
+
119
+ ```javascript
120
+ // After successful save
121
+ async save() {
122
+ try {
123
+ await this.customer.save()
124
+
125
+ this.$notify({
126
+ title: 'Customer saved successfully',
127
+ type: 'success'
128
+ })
129
+
130
+ this.$router.push('/customers')
131
+ } catch (error) {
132
+ this.$notify({
133
+ title: 'Failed to save customer',
134
+ type: 'error'
135
+ })
136
+ }
137
+ }
138
+
139
+ // After successful delete
140
+ async delete() {
141
+ await this.$axios.delete(`/api/customers/${id}`)
142
+
143
+ this.$notify({
144
+ title: 'Customer deleted',
145
+ type: 'success'
146
+ })
147
+ }
148
+
149
+ // Network error
150
+ catch (error) {
151
+ if (!error.response) {
152
+ this.$notify({
153
+ title: 'Network error. Please check your connection.',
154
+ type: 'error'
155
+ })
156
+ }
157
+ }
158
+
159
+ // Bulk action
160
+ this.$notify({
161
+ title: `${count} customers updated`,
162
+ type: 'success'
163
+ })
164
+ ```
165
+
166
+ ## $confirm
167
+
168
+ Show confirmation dialogs for destructive actions.
169
+
170
+ ### Basic Usage
171
+
172
+ ```javascript
173
+ const confirmed = await this.$confirm({
174
+ title: 'Delete Customer',
175
+ message: 'Are you sure you want to delete this customer?'
176
+ })
177
+
178
+ if (confirmed) {
179
+ // User clicked "Confirm"
180
+ await this.deleteCustomer()
181
+ } else {
182
+ // User clicked "Cancel" or closed dialog
183
+ }
184
+ ```
185
+
186
+ ### With Custom Button Text
187
+
188
+ ```javascript
189
+ const confirmed = await this.$confirm({
190
+ title: 'Permanent Delete',
191
+ message: 'This will permanently delete all data. This action cannot be undone.',
192
+ confirmText: 'Yes, Delete Everything',
193
+ cancelText: 'No, Keep It'
194
+ })
195
+ ```
196
+
197
+ ### Delete Pattern
198
+
199
+ ```javascript
200
+ async deleteCustomer(customer) {
201
+ const confirmed = await this.$confirm({
202
+ title: 'Delete Customer',
203
+ message: `Are you sure you want to delete ${customer.name}?`
204
+ })
205
+
206
+ if (!confirmed) {
207
+ return
208
+ }
209
+
210
+ try {
211
+ await this.$axios.delete(`/api/customers/${customer.id}`)
212
+
213
+ this.$notify({
214
+ title: 'Customer deleted',
215
+ type: 'success'
216
+ })
217
+
218
+ await this.customers.fetch()
219
+ } catch (error) {
220
+ this.$notify({
221
+ title: 'Failed to delete customer',
222
+ type: 'error'
223
+ })
224
+ }
225
+ }
226
+ ```
227
+
228
+ ### Discard Changes Pattern
229
+
230
+ ```javascript
231
+ async leave() {
232
+ if (this.hasUnsavedChanges) {
233
+ const confirmed = await this.$confirm({
234
+ title: 'Unsaved Changes',
235
+ message: 'You have unsaved changes. Are you sure you want to leave?',
236
+ confirmText: 'Leave',
237
+ cancelText: 'Stay'
238
+ })
239
+
240
+ if (!confirmed) {
241
+ return
242
+ }
243
+ }
244
+
245
+ this.$router.push('/customers')
246
+ }
247
+ ```
248
+
249
+ ### With Navigation Guard
250
+
251
+ ```javascript
252
+ export default {
253
+ beforeRouteLeave(to, from, next) {
254
+ if (this.hasUnsavedChanges) {
255
+ this.$confirm({
256
+ title: 'Unsaved Changes',
257
+ message: 'Are you sure you want to leave?'
258
+ }).then(confirmed => {
259
+ if (confirmed) {
260
+ next()
261
+ } else {
262
+ next(false)
263
+ }
264
+ })
265
+ } else {
266
+ next()
267
+ }
268
+ }
269
+ }
270
+ ```
271
+
272
+ ## $screen
273
+
274
+ Reactive responsive breakpoints.
275
+
276
+ ### Breakpoint Values
277
+
278
+ ```javascript
279
+ // Breakpoints (following Tailwind defaults)
280
+ $screen.sm // >= 640px
281
+ $screen.md // >= 768px
282
+ $screen.lg // >= 1024px
283
+ $screen.xl // >= 1280px
284
+ $screen.xxl // >= 1536px
285
+ ```
286
+
287
+ ### Usage in Templates
288
+
289
+ ```markup
290
+ <template>
291
+ <div>
292
+ <!-- Mobile only -->
293
+ <div v-if="!$screen.md">
294
+ Mobile menu
295
+ </div>
296
+
297
+ <!-- Desktop only -->
298
+ <div v-if="$screen.md">
299
+ Desktop menu
300
+ </div>
301
+
302
+ <!-- Responsive columns -->
303
+ <AwGrid :col="$screen.md ? 2 : 1">
304
+ <div>Column 1</div>
305
+ <div>Column 2</div>
306
+ </AwGrid>
307
+
308
+ <!-- Conditional component -->
309
+ <AwTable v-if="$screen.lg" :collection="items" />
310
+ <AwCard v-else v-for="item in items" :key="item.id">
311
+ {{ item.name }}
312
+ </AwCard>
313
+ </div>
314
+ </template>
315
+ ```
316
+
317
+ ### Usage in Methods
318
+
319
+ ```javascript
320
+ export default {
321
+ methods: {
322
+ openSidebar() {
323
+ // On mobile, open as modal
324
+ if (!this.$screen.md) {
325
+ this.showMobileMenu = true
326
+ }
327
+ },
328
+
329
+ getTableColumns() {
330
+ // Fewer columns on mobile
331
+ if (this.$screen.sm) {
332
+ return ['name', 'email', 'phone', 'created_at']
333
+ }
334
+ return ['name', 'email']
335
+ }
336
+ }
337
+ }
338
+ ```
339
+
340
+ ### Usage in Computed
341
+
342
+ ```javascript
343
+ export default {
344
+ computed: {
345
+ isMobile() {
346
+ return !this.$screen.md
347
+ },
348
+
349
+ columns() {
350
+ if (this.$screen.xl) {
351
+ return 4
352
+ }
353
+ if (this.$screen.lg) {
354
+ return 3
355
+ }
356
+ if (this.$screen.md) {
357
+ return 2
358
+ }
359
+ return 1
360
+ }
361
+ }
362
+ }
363
+ ```
364
+
365
+ ### Reactive Updates
366
+
367
+ `$screen` is reactive - components automatically update when breakpoints change:
368
+
369
+ ```markup
370
+ <template>
371
+ <div>
372
+ <!-- Automatically updates on resize -->
373
+ <p>Current breakpoint: {{ currentBreakpoint }}</p>
374
+ </div>
375
+ </template>
376
+
377
+ <script>
378
+ export default {
379
+ computed: {
380
+ currentBreakpoint() {
381
+ if (this.$screen.xxl) return 'xxl'
382
+ if (this.$screen.xl) return 'xl'
383
+ if (this.$screen.lg) return 'lg'
384
+ if (this.$screen.md) return 'md'
385
+ if (this.$screen.sm) return 'sm'
386
+ return 'xs'
387
+ }
388
+ }
389
+ }
390
+ </script>
391
+ ```
392
+
393
+ ## $dayjs
394
+
395
+ Date formatting and manipulation using Day.js library.
396
+
397
+ **⚠️ CRITICAL: Always use `$dayjs`, never use native `Date` constructor**
398
+
399
+ The framework uses Day.js for all date operations. Using native JavaScript `Date` constructor can cause timezone issues, inconsistent formatting, and compatibility problems. Always use `$dayjs` (in templates) or `this.$dayjs` (in methods) instead of `new Date()`.
400
+
401
+ ```javascript
402
+ // ❌ BAD - Never use native Date
403
+ const date = new Date(value)
404
+ date.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' })
405
+
406
+ // ✅ GOOD - Always use $dayjs
407
+ this.$dayjs(value).format('MMM D, YYYY')
408
+ ```
409
+
410
+ ### IMPORTANT: Template vs Method Usage
411
+
412
+ ```markup
413
+ <template>
414
+ <!-- ✅ GOOD: In templates, use $dayjs WITHOUT this -->
415
+ {{ $dayjs(date).format('ll') }}
416
+ </template>
417
+
418
+ <script>
419
+ export default {
420
+ methods: {
421
+ formatDate(date) {
422
+ // ✅ GOOD: In methods, use this.$dayjs WITH this
423
+ return this.$dayjs(date).format('ll')
424
+ }
425
+ }
426
+ }
427
+ </script>
428
+ ```
429
+
430
+ ### Common Date Formats
431
+
432
+ ```javascript
433
+ const date = '2024-01-15'
434
+
435
+ // Short date: Jan 15, 2024
436
+ this.$dayjs(date).format('ll')
437
+
438
+ // Long date: January 15, 2024
439
+ this.$dayjs(date).format('LL')
440
+
441
+ // Short date + time: Jan 15, 2024 2:30 PM
442
+ this.$dayjs(date).format('lll')
443
+
444
+ // Long date + time: January 15, 2024 2:30 PM
445
+ this.$dayjs(date).format('LLL')
446
+
447
+ // Full: Monday, January 15, 2024 2:30 PM
448
+ this.$dayjs(date).format('LLLL')
449
+
450
+ // Month and year: January 2024
451
+ this.$dayjs(date).format('MMMM YYYY')
452
+
453
+ // ISO format: 2024-01-15T14:30:00Z
454
+ this.$dayjs(date).toISOString()
455
+
456
+ // Relative time: 2 hours ago
457
+ this.$dayjs(date).fromNow()
458
+ ```
459
+
460
+ ### Template Usage
461
+
462
+ ```markup
463
+ <template>
464
+ <div>
465
+ <!-- Short date -->
466
+ <p>{{ $dayjs(customer.created_at).format('ll') }}</p>
467
+
468
+ <!-- Month and year -->
469
+ <p>{{ $dayjs(order.date).format('MMMM YYYY') }}</p>
470
+
471
+ <!-- Relative time -->
472
+ <p>Updated {{ $dayjs(item.updated_at).fromNow() }}</p>
473
+
474
+ <!-- Custom format -->
475
+ <p>{{ $dayjs(event.date).format('MMM D, YYYY [at] h:mm A') }}</p>
476
+ </div>
477
+ </template>
478
+ ```
479
+
480
+ ### Common Patterns
481
+
482
+ ```javascript
483
+ // Display created date
484
+ computed: {
485
+ createdDate() {
486
+ return this.$dayjs(this.customer.created_at).format('ll')
487
+ }
488
+ }
489
+
490
+ // Display relative time
491
+ computed: {
492
+ lastUpdated() {
493
+ return this.$dayjs(this.item.updated_at).fromNow()
494
+ }
495
+ }
496
+
497
+ // Filter by date range
498
+ methods: {
499
+ filterByMonth(month, year) {
500
+ const start = this.$dayjs(`${year}-${month}-01`).startOf('month')
501
+ const end = this.$dayjs(`${year}-${month}-01`).endOf('month')
502
+
503
+ return this.items.filter(item => {
504
+ const date = this.$dayjs(item.date)
505
+ return date.isAfter(start) && date.isBefore(end)
506
+ })
507
+ }
508
+ }
509
+
510
+ // Sort by date
511
+ methods: {
512
+ sortByDate() {
513
+ return this.items.sort((a, b) => {
514
+ return this.$dayjs(a.date).diff(this.$dayjs(b.date))
515
+ })
516
+ }
517
+ }
518
+ ```
519
+
520
+ ### Date Manipulation
521
+
522
+ ```javascript
523
+ // Add time
524
+ this.$dayjs().add(7, 'day') // 7 days from now
525
+ this.$dayjs().add(1, 'month') // 1 month from now
526
+ this.$dayjs().add(2, 'year') // 2 years from now
527
+
528
+ // Subtract time
529
+ this.$dayjs().subtract(3, 'day') // 3 days ago
530
+ this.$dayjs().subtract(1, 'week') // 1 week ago
531
+
532
+ // Start/end of period
533
+ this.$dayjs().startOf('month') // First day of month
534
+ this.$dayjs().endOf('month') // Last day of month
535
+ this.$dayjs().startOf('week') // Start of week (Sunday)
536
+
537
+ // Comparison
538
+ const date1 = this.$dayjs('2024-01-15')
539
+ const date2 = this.$dayjs('2024-02-20')
540
+
541
+ date1.isBefore(date2) // true
542
+ date1.isAfter(date2) // false
543
+ date1.isSame(date2) // false
544
+
545
+ // Difference
546
+ date2.diff(date1, 'day') // 36 days
547
+ date2.diff(date1, 'month') // 1 month
548
+ ```
549
+
550
+ ## router.pushBack / router.setBack
551
+
552
+ Navigate back to a specific route.
553
+
554
+ ### Basic Usage
555
+
556
+ ```javascript
557
+ // Set where "back" should go
558
+ this.$router.setBack('/customers')
559
+
560
+ // Navigate back
561
+ this.$router.pushBack()
562
+ ```
563
+
564
+ ### Common Pattern
565
+
566
+ ```javascript
567
+ // On list page - set back route
568
+ mounted() {
569
+ this.$router.setBack('/customers')
570
+ }
571
+
572
+ // On detail page - go back
573
+ methods: {
574
+ cancel() {
575
+ this.$router.pushBack()
576
+ }
577
+ }
578
+ ```
579
+
580
+ ### With Fallback
581
+
582
+ ```javascript
583
+ // Go back, or fallback to /dashboard
584
+ this.$router.pushBack('/dashboard')
585
+ ```
586
+
587
+ ### Complete Example
588
+
589
+ ```markup
590
+ <!-- List Page -->
591
+ <script>
592
+ export default {
593
+ mounted() {
594
+ // Set back route for detail pages
595
+ this.$router.setBack(`/shops/${this.$route.params.shop_uuid}/customers`)
596
+ },
597
+
598
+ methods: {
599
+ viewCustomer(customer) {
600
+ this.$router.push(`/shops/${this.$route.params.shop_uuid}/customers/${customer.id}`)
601
+ }
602
+ }
603
+ }
604
+ </script>
605
+
606
+ <!-- Detail Page -->
607
+ <script>
608
+ export default {
609
+ methods: {
610
+ async save() {
611
+ await this.customer.save()
612
+
613
+ this.$notify({
614
+ title: 'Customer saved',
615
+ type: 'success'
616
+ })
617
+
618
+ // Go back to list
619
+ this.$router.pushBack(`/shops/${this.$route.params.shop_uuid}/customers`)
620
+ },
621
+
622
+ cancel() {
623
+ // Go back without saving
624
+ this.$router.pushBack(`/shops/${this.$route.params.shop_uuid}/customers`)
625
+ }
626
+ }
627
+ }
628
+ </script>
629
+ ```
630
+
631
+ ## $awes
632
+
633
+ Access AwesCode UI configuration and utilities.
634
+
635
+ ### Configuration Access
636
+
637
+ ```javascript
638
+ // Get component config
639
+ const buttonConfig = this.$awes.config.AwButton
640
+
641
+ // Get global config
642
+ const apiUrl = this.$awes.config.apiUrl
643
+ ```
644
+
645
+ ### Usage
646
+
647
+ ```javascript
648
+ export default {
649
+ computed: {
650
+ defaultButtonSize() {
651
+ return this.$awes.config.AwButton?.size || 'md'
652
+ }
653
+ }
654
+ }
655
+ ```
656
+
657
+ ## $can / $cannot (CASL Permissions)
658
+
659
+ Check user permissions (if CASL is configured).
660
+
661
+ ### Basic Usage
662
+
663
+ ```markup
664
+ <template>
665
+ <div>
666
+ <!-- Show button only if user can create -->
667
+ <AwButton v-if="$can('create', 'Customer')">
668
+ Add Customer
669
+ </AwButton>
670
+
671
+ <!-- Show button only if user can edit -->
672
+ <AwButton v-if="$can('update', customer)">
673
+ Edit
674
+ </AwButton>
675
+
676
+ <!-- Show button only if user can delete -->
677
+ <AwButton v-if="$can('delete', customer)">
678
+ Delete
679
+ </AwButton>
680
+
681
+ <!-- Inverse check -->
682
+ <p v-if="$cannot('view', 'Reports')">
683
+ You don't have access to reports
684
+ </p>
685
+ </div>
686
+ </template>
687
+ ```
688
+
689
+ ### In Methods
690
+
691
+ ```javascript
692
+ export default {
693
+ methods: {
694
+ async deleteCustomer(customer) {
695
+ // Check permission
696
+ if (!this.$can('delete', customer)) {
697
+ this.$notify({
698
+ title: 'You do not have permission to delete this customer',
699
+ type: 'error'
700
+ })
701
+ return
702
+ }
703
+
704
+ // Proceed with delete
705
+ await this.$axios.delete(`/api/customers/${customer.id}`)
706
+ }
707
+ }
708
+ }
709
+ ```
710
+
711
+ ## Dark Theme Management
712
+
713
+ Toggle between light and dark themes using Vuex store.
714
+
715
+ ### Basic Usage
716
+
717
+ ```markup
718
+ <template>
719
+ <AwButton @click="toggleTheme">
720
+ Toggle Theme
721
+ </AwButton>
722
+ </template>
723
+
724
+ <script>
725
+ export default {
726
+ methods: {
727
+ toggleTheme() {
728
+ const currentTheme = this.$store.getters['awesIo/isDarkTheme']
729
+ this.$store.commit('awesIo/SET_DARK_THEME', !currentTheme)
730
+ }
731
+ }
732
+ }
733
+ </script>
734
+ ```
735
+
736
+ ### Using v-model with Switcher
737
+
738
+ ```markup
739
+ <template>
740
+ <AwSwitcher v-model="isDarkTheme" size="lg" />
741
+ </template>
742
+
743
+ <script>
744
+ export default {
745
+ computed: {
746
+ isDarkTheme: {
747
+ get() {
748
+ return this.$store.getters['awesIo/isDarkTheme']
749
+ },
750
+ set(val) {
751
+ this.$store.commit('awesIo/SET_DARK_THEME', val)
752
+ }
753
+ }
754
+ }
755
+ }
756
+ </script>
757
+ ```
758
+
759
+ ### With Icon Button
760
+
761
+ ```markup
762
+ <template>
763
+ <AwButton @click="toggleTheme">
764
+ <AwIcon :name="isDarkTheme ? 'sun' : 'moon'" />
765
+ {{ isDarkTheme ? 'Light Mode' : 'Dark Mode' }}
766
+ </AwButton>
767
+ </template>
768
+
769
+ <script>
770
+ export default {
771
+ computed: {
772
+ isDarkTheme() {
773
+ return this.$store.getters['awesIo/isDarkTheme']
774
+ }
775
+ },
776
+
777
+ methods: {
778
+ toggleTheme() {
779
+ this.$store.commit('awesIo/SET_DARK_THEME', !this.isDarkTheme)
780
+ }
781
+ }
782
+ }
783
+ </script>
784
+ ```
785
+
786
+ ## Complete Examples
787
+
788
+ ### Form with Full Error Handling
789
+
790
+ ```markup
791
+ <template>
792
+ <AwPageSingle
793
+ hide-menu
794
+ :title="customer.isNew() ? 'New Customer' : 'Edit Customer'"
795
+ >
796
+ <AwCard title="Customer Information">
797
+ <AwInput
798
+ v-model="customer.name"
799
+ :error="customer.errors.name"
800
+ label="Name"
801
+ />
802
+
803
+ <AwInput
804
+ v-model="customer.email"
805
+ :error="customer.errors.email"
806
+ label="Email"
807
+ type="email"
808
+ />
809
+
810
+ <AwDate
811
+ v-model="customer.birthday"
812
+ :error="customer.errors.birthday"
813
+ label="Birthday"
814
+ />
815
+
816
+ <!-- Display formatted date -->
817
+ <p v-if="customer.birthday">
818
+ Birthday: {{ $dayjs(customer.birthday).format('LL') }}
819
+ </p>
820
+ </AwCard>
821
+
822
+ <template #buttons>
823
+ <AwButton
824
+ :loading="saving"
825
+ color="accent"
826
+ @click="save"
827
+ >
828
+ Save
829
+ </AwButton>
830
+
831
+ <AwButton @click="cancel">
832
+ Cancel
833
+ </AwButton>
834
+ </template>
835
+ </AwPageSingle>
836
+ </template>
837
+
838
+ <script>
839
+ import Customer from '~/models/Customer'
840
+
841
+ export default {
842
+ data() {
843
+ return {
844
+ customer: new Customer(
845
+ {},
846
+ null,
847
+ { shop_uuid: this.$route.params.shop_uuid }
848
+ ),
849
+ saving: false
850
+ }
851
+ },
852
+
853
+ methods: {
854
+ async save() {
855
+ this.saving = true
856
+
857
+ try {
858
+ await this.customer.save()
859
+
860
+ if (Object.keys(this.customer.errors).length > 0) {
861
+ this.$notify({
862
+ title: 'Please fix validation errors',
863
+ type: 'error'
864
+ })
865
+ return
866
+ }
867
+
868
+ this.$notify({
869
+ title: 'Customer saved successfully',
870
+ type: 'success'
871
+ })
872
+
873
+ this.$router.pushBack(`/shops/${this.$route.params.shop_uuid}/customers`)
874
+ } catch (error) {
875
+ this.$notify({
876
+ title: 'Failed to save customer',
877
+ type: 'error'
878
+ })
879
+ } finally {
880
+ this.saving = false
881
+ }
882
+ },
883
+
884
+ cancel() {
885
+ this.$router.pushBack(`/shops/${this.$route.params.shop_uuid}/customers`)
886
+ }
887
+ }
888
+ }
889
+ </script>
890
+ ```
891
+
892
+ ### Responsive Table
893
+
894
+ ```markup
895
+ <template>
896
+ <AwPage title="Customers">
897
+ <template #buttons>
898
+ <AwButton
899
+ v-if="$can('create', 'Customer')"
900
+ :href="`/shops/${$route.params.shop_uuid}/customers/new`"
901
+ color="accent"
902
+ >
903
+ Add Customer
904
+ </AwButton>
905
+ </template>
906
+
907
+ <!-- Desktop table -->
908
+ <AwTableBuilder
909
+ v-if="$screen.md"
910
+ :collection="customers"
911
+ @click:row="viewCustomer"
912
+ >
913
+ <AwTableCol field="name" title="Name" />
914
+ <AwTableCol field="email" title="Email" />
915
+ <AwTableCol field="phone" title="Phone" />
916
+ <AwTableCol field="created_at" title="Created">
917
+ <template #default="{ cell }">
918
+ {{ $dayjs(cell).format('ll') }}
919
+ </template>
920
+ </AwTableCol>
921
+ </AwTableBuilder>
922
+
923
+ <!-- Mobile cards -->
924
+ <div v-else>
925
+ <AwCard
926
+ v-for="customer in customers.models"
927
+ :key="customer.id"
928
+ class="mb-4"
929
+ @click="viewCustomer(customer)"
930
+ >
931
+ <h3>{{ customer.name }}</h3>
932
+ <p>{{ customer.email }}</p>
933
+ <p class="text-sm text-gray-500">
934
+ Created {{ $dayjs(customer.created_at).fromNow() }}
935
+ </p>
936
+ </AwCard>
937
+ </div>
938
+ </AwPage>
939
+ </template>
940
+
941
+ <script>
942
+ import Customers from '~/collections/Customers'
943
+
944
+ export default {
945
+ data() {
946
+ return {
947
+ customers: new Customers([], {
948
+ shop_uuid: this.$route.params.shop_uuid
949
+ })
950
+ }
951
+ },
952
+
953
+ mounted() {
954
+ this.$router.setBack(`/shops/${this.$route.params.shop_uuid}/customers`)
955
+ },
956
+
957
+ methods: {
958
+ viewCustomer(customer) {
959
+ this.$router.push(`/shops/${this.$route.params.shop_uuid}/customers/${customer.id}`)
960
+ }
961
+ }
962
+ }
963
+ </script>
964
+ ```
965
+
966
+ ## See Also
967
+
968
+ - [Error Handling Guide](../guides/error-handling.md) - Using $notify and $confirm
969
+ - [Data Fetching Guide](../guides/data-fetching.md) - Using date formatting in templates
970
+ - [Best Practices Guide](../guides/best-practices.md) - Plugin usage patterns