admin-lte 4.0.2 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/ACCESSIBILITY-COMPLIANCE.md +60 -339
  2. package/CHANGELOG.md +66 -0
  3. package/README.md +15 -2
  4. package/dist/css/adminlte-docs.css +878 -0
  5. package/dist/css/adminlte-docs.css.map +1 -0
  6. package/dist/css/adminlte-docs.min.css +7 -0
  7. package/dist/css/adminlte-docs.min.css.map +1 -0
  8. package/dist/css/adminlte-docs.rtl.css +877 -0
  9. package/dist/css/adminlte-docs.rtl.css.map +1 -0
  10. package/dist/css/adminlte-docs.rtl.min.css +7 -0
  11. package/dist/css/adminlte-docs.rtl.min.css.map +1 -0
  12. package/dist/css/adminlte.css +1176 -2718
  13. package/dist/css/adminlte.css.map +1 -1
  14. package/dist/css/adminlte.min.css +2 -2
  15. package/dist/css/adminlte.min.css.map +1 -1
  16. package/dist/css/adminlte.rtl.css +1176 -2718
  17. package/dist/css/adminlte.rtl.css.map +1 -1
  18. package/dist/css/adminlte.rtl.min.css +2 -2
  19. package/dist/css/adminlte.rtl.min.css.map +1 -1
  20. package/dist/js/adminlte.esm.js +1365 -0
  21. package/dist/js/adminlte.esm.js.map +1 -0
  22. package/dist/js/adminlte.esm.min.js +7 -0
  23. package/dist/js/adminlte.esm.min.js.map +1 -0
  24. package/dist/js/adminlte.js +606 -310
  25. package/dist/js/adminlte.js.map +1 -1
  26. package/dist/js/adminlte.min.js +2 -2
  27. package/dist/js/adminlte.min.js.map +1 -1
  28. package/dist/js/types/accessibility.d.ts +46 -0
  29. package/dist/js/types/adminlte.d.ts +9 -0
  30. package/dist/js/types/base-component.d.ts +36 -0
  31. package/dist/js/types/card-widget.d.ts +30 -0
  32. package/dist/js/types/color-mode.d.ts +56 -0
  33. package/dist/js/types/direct-chat.d.ts +19 -0
  34. package/dist/js/types/fullscreen.d.ts +21 -0
  35. package/dist/js/types/layout.d.ts +19 -0
  36. package/dist/js/types/push-menu.d.ts +102 -0
  37. package/dist/js/types/treeview.d.ts +27 -0
  38. package/dist/js/types/util/index.d.ts +42 -0
  39. package/package.json +60 -21
  40. package/src/scss/_app-header.scss +3 -1
  41. package/src/scss/_app-main.scss +4 -0
  42. package/src/scss/_app-sidebar.scss +3 -1
  43. package/src/scss/_bootstrap-overrides.scss +60 -0
  44. package/src/scss/_callouts.scss +13 -3
  45. package/src/scss/_dropdown.scss +3 -1
  46. package/src/scss/_info-box.scss +3 -1
  47. package/src/scss/_progress-bars.scss +3 -1
  48. package/src/scss/_table.scss +4 -2
  49. package/src/scss/adminlte-docs.scss +25 -0
  50. package/src/scss/adminlte.scss +5 -4
  51. package/src/scss/pages/_login_and_register.scss +3 -1
  52. package/src/scss/parts/_core.scss +0 -1
  53. package/src/ts/accessibility.ts +129 -69
  54. package/src/ts/adminlte.ts +3 -1
  55. package/src/ts/base-component.ts +84 -0
  56. package/src/ts/card-widget.ts +134 -85
  57. package/src/ts/color-mode.ts +174 -0
  58. package/src/ts/direct-chat.ts +38 -32
  59. package/src/ts/fullscreen.ts +78 -63
  60. package/src/ts/layout.ts +2 -1
  61. package/src/ts/push-menu.ts +93 -44
  62. package/src/ts/treeview.ts +107 -47
  63. package/src/ts/util/index.ts +114 -29
  64. package/.browserslistrc +0 -17
  65. package/.prettierrc +0 -6
  66. package/CODE_OF_CONDUCT.md +0 -43
  67. package/SECURITY.md +0 -99
  68. package/dist/UI/general.html +0 -2317
  69. package/dist/UI/icons.html +0 -1126
  70. package/dist/UI/timeline.html +0 -1212
  71. package/dist/docs/browser-support.html +0 -826
  72. package/dist/docs/color-mode.html +0 -1142
  73. package/dist/docs/components/main-header.html +0 -1209
  74. package/dist/docs/components/main-sidebar.html +0 -924
  75. package/dist/docs/customization.html +0 -1080
  76. package/dist/docs/deployment.html +0 -1145
  77. package/dist/docs/faq.html +0 -1392
  78. package/dist/docs/getting-started.html +0 -991
  79. package/dist/docs/how-to-contribute.html +0 -890
  80. package/dist/docs/index.html +0 -16
  81. package/dist/docs/integrations.html +0 -1231
  82. package/dist/docs/introduction.html +0 -1008
  83. package/dist/docs/javascript/accessibility.html +0 -949
  84. package/dist/docs/javascript/card-widget.html +0 -1019
  85. package/dist/docs/javascript/direct-chat.html +0 -896
  86. package/dist/docs/javascript/fullscreen.html +0 -905
  87. package/dist/docs/javascript/layout.html +0 -908
  88. package/dist/docs/javascript/plugins-overview.html +0 -1144
  89. package/dist/docs/javascript/pushmenu.html +0 -1045
  90. package/dist/docs/javascript/treeview.html +0 -1024
  91. package/dist/docs/layout-blueprint.html +0 -1087
  92. package/dist/docs/layout.html +0 -842
  93. package/dist/docs/license.html +0 -807
  94. package/dist/docs/migration.html +0 -1149
  95. package/dist/docs/recipes.html +0 -1185
  96. package/dist/docs/rtl.html +0 -957
  97. package/dist/examples/lockscreen.html +0 -249
  98. package/dist/examples/login-v2.html +0 -282
  99. package/dist/examples/login.html +0 -272
  100. package/dist/examples/register-v2.html +0 -291
  101. package/dist/examples/register.html +0 -277
  102. package/dist/forms/elements.html +0 -1405
  103. package/dist/forms/layout.html +0 -1267
  104. package/dist/forms/validation.html +0 -1275
  105. package/dist/forms/wizard.html +0 -1410
  106. package/dist/generate/theme.html +0 -1082
  107. package/dist/index.html +0 -1745
  108. package/dist/index2.html +0 -2277
  109. package/dist/index3.html +0 -1532
  110. package/dist/layout/collapsed-sidebar-without-hover.html +0 -1144
  111. package/dist/layout/collapsed-sidebar.html +0 -1137
  112. package/dist/layout/fixed-complete.html +0 -1138
  113. package/dist/layout/fixed-footer.html +0 -1136
  114. package/dist/layout/fixed-header.html +0 -1136
  115. package/dist/layout/fixed-sidebar.html +0 -1138
  116. package/dist/layout/layout-custom-area.html +0 -1177
  117. package/dist/layout/layout-rtl.html +0 -1137
  118. package/dist/layout/logo-switch.html +0 -683
  119. package/dist/layout/sidebar-mini.html +0 -1137
  120. package/dist/layout/unfixed-sidebar.html +0 -1136
  121. package/dist/mailbox/compose.html +0 -1151
  122. package/dist/mailbox/inbox.html +0 -1509
  123. package/dist/mailbox/read.html +0 -1202
  124. package/dist/pages/404.html +0 -239
  125. package/dist/pages/500.html +0 -227
  126. package/dist/pages/calendar.html +0 -1266
  127. package/dist/pages/chat.html +0 -1427
  128. package/dist/pages/faq.html +0 -1383
  129. package/dist/pages/file-manager.html +0 -1835
  130. package/dist/pages/invoice.html +0 -1199
  131. package/dist/pages/kanban.html +0 -1439
  132. package/dist/pages/maintenance.html +0 -230
  133. package/dist/pages/pricing.html +0 -1279
  134. package/dist/pages/profile.html +0 -1382
  135. package/dist/pages/projects.html +0 -1644
  136. package/dist/pages/settings.html +0 -1387
  137. package/dist/tables/data.html +0 -1319
  138. package/dist/tables/simple.html +0 -1435
  139. package/dist/widgets/cards.html +0 -1356
  140. package/dist/widgets/info-box.html +0 -1429
  141. package/dist/widgets/small-box.html +0 -1225
  142. package/eslint.config.js +0 -82
  143. package/github-issue-response.md +0 -40
  144. package/index.html +0 -12
  145. package/netlify.toml +0 -16
  146. package/src/scss/_bootstrap-variables.scss +0 -1766
@@ -1,22 +1,80 @@
1
- const domContentLoadedCallbacks: Array<() => void> = []
1
+ /**
2
+ * Lifecycle management
3
+ * ============================================================================
4
+ *
5
+ * Plugins register their initialisation through `onDOMContentLoaded`. Besides
6
+ * the initial page load, every registered callback is re-run on Hotwired Turbo
7
+ * navigations (`turbo:load`): Turbo Drive swaps the <body> without a full page
8
+ * reload, so without re-initialisation plugins such as PushMenu and TreeView
9
+ * stop working after the first in-app link click (#563, #5890).
10
+ *
11
+ * Re-running init would normally leak listeners, because callbacks also bind to
12
+ * `window`/`document`, which survive Turbo's <body> swap. To prevent that, each
13
+ * cycle has its own `AbortController`: callbacks should attach their
14
+ * window/document-level listeners with the signal from `getLifecycleSignal()`.
15
+ * The signal is aborted on `turbo:before-render`, tearing down the previous
16
+ * cycle's listeners before the callbacks run again. Listeners bound to elements
17
+ * inside <body> don't need the signal — Turbo discards the old <body>, so they
18
+ * are cleaned up automatically.
19
+ */
20
+
21
+ const lifecycleCallbacks: Array<() => void> = []
22
+
23
+ // Mutable state is held on an object so the lifecycle hooks below can update it
24
+ // without reassigning top-level bindings.
25
+ const lifecycleState = {
26
+ controller: new AbortController(),
27
+ hasInitialized: false
28
+ }
29
+
30
+ /**
31
+ * The AbortSignal for the current lifecycle. Pass it as the
32
+ * `{ signal }` option to window/document `addEventListener` calls made during
33
+ * initialisation so they are removed automatically on the next Turbo render.
34
+ */
35
+ const getLifecycleSignal = (): AbortSignal => lifecycleState.controller.signal
36
+
37
+ const runLifecycleCallbacks = (): void => {
38
+ if (lifecycleState.hasInitialized) {
39
+ return
40
+ }
41
+
42
+ lifecycleState.hasInitialized = true
43
+
44
+ for (const callback of lifecycleCallbacks) {
45
+ callback()
46
+ }
47
+ }
2
48
 
3
49
  const onDOMContentLoaded = (callback: () => void): void => {
4
- if (document.readyState === 'loading') {
5
- // add listener on the first call when the document is in loading state
6
- if (!domContentLoadedCallbacks.length) {
7
- document.addEventListener('DOMContentLoaded', () => {
8
- for (const callback of domContentLoadedCallbacks) {
9
- callback()
10
- }
11
- })
12
- }
13
-
14
- domContentLoadedCallbacks.push(callback)
15
- } else {
50
+ lifecycleCallbacks.push(callback)
51
+
52
+ // Late registration: the batch for the current cycle has already run (the
53
+ // script loaded after DOMContentLoaded, or a callback was registered after a
54
+ // Turbo visit), so run the newcomer immediately rather than stranding it
55
+ // until the next navigation. Preserves the original non-loading behaviour.
56
+ if (lifecycleState.hasInitialized) {
16
57
  callback()
17
58
  }
18
59
  }
19
60
 
61
+ // Initial page load.
62
+ if (document.readyState === 'loading') {
63
+ document.addEventListener('DOMContentLoaded', runLifecycleCallbacks, { once: true })
64
+ } else {
65
+ runLifecycleCallbacks()
66
+ }
67
+
68
+ // Hotwired Turbo: drop the previous cycle's window/document listeners, then
69
+ // re-run initialisation against the freshly rendered <body>.
70
+ document.addEventListener('turbo:before-render', () => {
71
+ lifecycleState.controller.abort()
72
+ lifecycleState.controller = new AbortController()
73
+ lifecycleState.hasInitialized = false
74
+ })
75
+
76
+ document.addEventListener('turbo:load', runLifecycleCallbacks)
77
+
20
78
  /* ES2022 UTILITY FUNCTIONS */
21
79
 
22
80
  /**
@@ -46,10 +104,35 @@ const safePropertyAccess = (obj: Record<string, unknown>, property: string): unk
46
104
  }
47
105
  }
48
106
 
107
+ /* SLIDE ANIMATION BOOKKEEPING
108
+ * Pending timers are tracked per element so that starting a new slide cancels
109
+ * the previous animation's steps: without this, rapidly toggling a treeview or
110
+ * card leaves a stale cleanup timer that strips height/transition mid-animation
111
+ * and desyncs the element's display state from its component's classes. */
112
+ const slideTimers = new WeakMap<HTMLElement, Array<ReturnType<typeof globalThis.setTimeout>>>()
113
+
114
+ const cancelSlide = (target: HTMLElement): void => {
115
+ const timers = slideTimers.get(target) ?? []
116
+ for (const timer of timers) {
117
+ globalThis.clearTimeout(timer)
118
+ }
119
+
120
+ slideTimers.delete(target)
121
+ }
122
+
123
+ const clearSlideStyles = (target: HTMLElement): void => {
124
+ for (const property of ['height', 'padding-top', 'padding-bottom', 'margin-top', 'margin-bottom', 'overflow', 'transition-duration', 'transition-property']) {
125
+ target.style.removeProperty(property)
126
+ }
127
+ }
128
+
49
129
  /* SLIDE UP */
50
130
  const slideUp = (target: HTMLElement, duration = 500) => {
131
+ cancelSlide(target)
132
+
51
133
  if (duration <= 1) {
52
134
  target.style.display = 'none'
135
+ clearSlideStyles(target)
53
136
  return
54
137
  }
55
138
 
@@ -59,7 +142,7 @@ const slideUp = (target: HTMLElement, duration = 500) => {
59
142
  target.style.height = `${target.offsetHeight}px`
60
143
  target.style.overflow = 'hidden'
61
144
 
62
- globalThis.setTimeout(() => {
145
+ const stepTimer = globalThis.setTimeout(() => {
63
146
  target.style.height = '0'
64
147
  target.style.paddingTop = '0'
65
148
  target.style.paddingBottom = '0'
@@ -67,21 +150,22 @@ const slideUp = (target: HTMLElement, duration = 500) => {
67
150
  target.style.marginBottom = '0'
68
151
  }, 1)
69
152
 
70
- globalThis.setTimeout(() => {
153
+ const cleanupTimer = globalThis.setTimeout(() => {
71
154
  target.style.display = 'none'
72
- target.style.removeProperty('height')
73
- target.style.removeProperty('padding-top')
74
- target.style.removeProperty('padding-bottom')
75
- target.style.removeProperty('margin-top')
76
- target.style.removeProperty('margin-bottom')
77
- target.style.removeProperty('overflow')
78
- target.style.removeProperty('transition-duration')
79
- target.style.removeProperty('transition-property')
155
+ clearSlideStyles(target)
156
+ slideTimers.delete(target)
80
157
  }, duration)
158
+
159
+ slideTimers.set(target, [stepTimer, cleanupTimer])
81
160
  }
82
161
 
83
162
  /* SLIDE DOWN */
84
163
  const slideDown = (target: HTMLElement, duration = 500) => {
164
+ cancelSlide(target)
165
+ // Drop inline styles a cancelled slideUp may have left behind (height: 0,
166
+ // overflow: hidden, …) before measuring, or the natural height reads as 0.
167
+ clearSlideStyles(target)
168
+
85
169
  target.style.removeProperty('display')
86
170
  let { display } = globalThis.getComputedStyle(target)
87
171
 
@@ -103,7 +187,7 @@ const slideDown = (target: HTMLElement, duration = 500) => {
103
187
  target.style.marginTop = '0'
104
188
  target.style.marginBottom = '0'
105
189
 
106
- globalThis.setTimeout(() => {
190
+ const stepTimer = globalThis.setTimeout(() => {
107
191
  target.style.boxSizing = 'border-box'
108
192
  target.style.transitionProperty = 'height, margin, padding'
109
193
  target.style.transitionDuration = `${duration}ms`
@@ -114,12 +198,12 @@ const slideDown = (target: HTMLElement, duration = 500) => {
114
198
  target.style.removeProperty('margin-bottom')
115
199
  }, 1)
116
200
 
117
- globalThis.setTimeout(() => {
118
- target.style.removeProperty('height')
119
- target.style.removeProperty('overflow')
120
- target.style.removeProperty('transition-duration')
121
- target.style.removeProperty('transition-property')
201
+ const cleanupTimer = globalThis.setTimeout(() => {
202
+ clearSlideStyles(target)
203
+ slideTimers.delete(target)
122
204
  }, duration)
205
+
206
+ slideTimers.set(target, [stepTimer, cleanupTimer])
123
207
  }
124
208
 
125
209
  /* TOGGLE */
@@ -134,6 +218,7 @@ const slideToggle = (target: HTMLElement, duration = 500) => {
134
218
 
135
219
  export {
136
220
  onDOMContentLoaded,
221
+ getLifecycleSignal,
137
222
  slideUp,
138
223
  slideDown,
139
224
  slideToggle,
package/.browserslistrc DELETED
@@ -1,17 +0,0 @@
1
- # https://github.com/browserslist/browserslist#readme
2
- # Updated for ES2022 compatibility
3
-
4
- >= 0.5%
5
- last 2 major versions
6
- not dead
7
- Chrome >= 97
8
- Firefox >= 104
9
- Firefox ESR
10
- iOS >= 15.4
11
- Safari >= 15.4
12
- Edge >= 97
13
- not Explorer <= 11
14
- not ie 11
15
- not android 4.4.3
16
- not ios_saf < 15.4
17
- not kaios <= 2.5 # fix floating label issues in Firefox (see https://github.com/postcss/autoprefixer/issues/1533)
package/.prettierrc DELETED
@@ -1,6 +0,0 @@
1
- {
2
- "semi": true,
3
- "singleQuote": true,
4
- "printWidth": 100,
5
- "tabWidth": 2
6
- }
@@ -1,43 +0,0 @@
1
- # Contributor Covenant Code of Conduct
2
-
3
- ## Our Pledge
4
-
5
- In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6
-
7
- ## Our Standards
8
-
9
- Examples of behavior that contributes to creating a positive environment include:
10
-
11
- - Using welcoming and inclusive language
12
- - Being respectful of differing viewpoints and experiences
13
- - Gracefully accepting constructive criticism
14
- - Focusing on what is best for the community
15
- - Showing empathy towards other community members
16
-
17
- Examples of unacceptable behavior by participants include:
18
-
19
- - The use of sexualized language or imagery and unwelcome sexual attention or advances
20
- - Trolling, insulting/derogatory comments, and personal or political attacks
21
- - Public or private harassment
22
- - Publishing others' private information, such as a physical or electronic address, without explicit permission
23
- - Other conduct which could reasonably be considered inappropriate in a professional setting
24
-
25
- ## Our Responsibilities
26
-
27
- Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28
-
29
- Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30
-
31
- ## Scope
32
-
33
- This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34
-
35
- ## Enforcement
36
-
37
- Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at https://colorlib.com/wp/contact-us/. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38
-
39
- Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40
-
41
- ## Attribution
42
-
43
- This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/), version 1.4, available at <https://www.contributor-covenant.org/version/1/4/code-of-conduct/>
package/SECURITY.md DELETED
@@ -1,99 +0,0 @@
1
- # Security Policy
2
-
3
- ## Reporting Security Issues
4
-
5
- If you discover a security vulnerability in AdminLTE, please report it by emailing the maintainers or opening a private security advisory on GitHub. We take security seriously and will respond promptly.
6
-
7
- ## Supported Versions
8
-
9
- | Version | Supported |
10
- | ------- | ------------------ |
11
- | 4.x | :white_check_mark: |
12
- | 3.x | :x: |
13
- | < 3.0 | :x: |
14
-
15
- ## Security Best Practices
16
-
17
- AdminLTE is a frontend admin dashboard template. When deploying applications built with AdminLTE, follow these security best practices:
18
-
19
- ### 1. Production Deployment
20
-
21
- - **Never expose `node_modules` directory** in production environments
22
- - **Remove demo/example files** (like `index2.html`, `index3.html`) from production builds
23
- - **Use a proper build process** that only includes necessary production assets
24
- - **Configure web server properly** to prevent directory traversal attacks
25
-
26
- ### 2. Build Process
27
-
28
- When deploying to production:
29
-
30
- ```bash
31
- # Build only production assets
32
- npm run production
33
-
34
- # Deploy only the dist/ directory contents you need
35
- # Typically: dist/js/adminlte.min.js and dist/css/adminlte.min.css
36
- ```
37
-
38
- ### 3. What NOT to Deploy
39
-
40
- Do not deploy these to production:
41
- - `node_modules/` directory
42
- - Example/demo HTML files (`index.html`, `index2.html`, `index3.html`, etc.)
43
- - Source files (`src/` directory)
44
- - Development configuration files
45
- - Documentation files
46
-
47
- ## Known CVE Issues
48
-
49
- ### CVE-2021-36471 (Disputed)
50
-
51
- **Status**: This CVE is **disputed** and does not represent a vulnerability in AdminLTE itself.
52
-
53
- **Issue**: CVE-2021-36471 claims AdminLTE 3.1.0 has a "Directory Traversal vulnerability" that allows remote attackers to view demo pages via `/admin/index2.html` and `/admin/index3.html`.
54
-
55
- **Clarification**:
56
- - The `index2.html` and `index3.html` files are **example/demo pages** intended for developer reference during development
57
- - This is **not a vulnerability in AdminLTE** - it is a **deployment misconfiguration** by website developers
58
- - The issue occurs when developers incorrectly deploy:
59
- - Their entire `node_modules` folder publicly
60
- - Demo/example files in production environments
61
- - Without proper web server configuration
62
-
63
- **Resolution**:
64
- - AdminLTE 4.x has restructured the project architecture with clear separation between development demos and production assets
65
- - Follow the production deployment best practices above
66
- - Only deploy the compiled production assets from `dist/js/` and `dist/css/`
67
- - The original CVE researcher acknowledged this should be classified as low/info severity, not critical
68
-
69
- **For More Information**:
70
- - [GitHub Issue #4948](https://github.com/ColorlibHQ/AdminLTE/issues/4948)
71
- - [CVE Record](https://www.cve.org/CVERecord?id=CVE-2021-36471) (marked as disputed)
72
-
73
- ## Secure Development
74
-
75
- ### Content Security Policy (CSP)
76
-
77
- When implementing AdminLTE in your application, consider adding appropriate Content Security Policy headers to prevent XSS attacks.
78
-
79
- ### Authentication & Authorization
80
-
81
- AdminLTE is a **UI template only** and does not include authentication or authorization. You must:
82
- - Implement proper authentication in your backend
83
- - Secure all API endpoints
84
- - Use HTTPS in production
85
- - Implement proper session management
86
- - Follow OWASP security guidelines
87
-
88
- ### Dependencies
89
-
90
- - Keep AdminLTE and its dependencies up to date
91
- - Regularly run `npm audit` to check for vulnerabilities
92
- - Review security advisories for Bootstrap and other dependencies
93
-
94
- ## Contact
95
-
96
- For security concerns, please contact the maintainers through:
97
- - GitHub Issues (for general questions)
98
- - GitHub Security Advisories (for sensitive security issues)
99
- - Project maintainer email (check package.json)