@keenmate/pure-admin-core 2.1.0 → 2.1.1

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.
package/dist/css/main.css CHANGED
@@ -3061,7 +3061,7 @@ body.loaded .pa-sidebar__link {
3061
3061
  background-color: var(--pa-accent-light);
3062
3062
  }
3063
3063
  .pa-sidebar__link--active {
3064
- color: var(--pa-sidebar-text);
3064
+ color: var(--pa-accent);
3065
3065
  background-color: var(--pa-accent-hover);
3066
3066
  border-inline-end-color: var(--pa-accent);
3067
3067
  font-weight: 600;
@@ -3087,7 +3087,7 @@ body.loaded .pa-sidebar__toggle {
3087
3087
  background-color: var(--pa-accent-light);
3088
3088
  }
3089
3089
  .pa-sidebar__toggle--active {
3090
- color: var(--pa-sidebar-text);
3090
+ color: var(--pa-accent);
3091
3091
  background-color: var(--pa-accent-hover);
3092
3092
  }
3093
3093
  .pa-sidebar__icon {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keenmate/pure-admin-core",
3
- "version": "2.1.0",
3
+ "version": "2.1.1",
4
4
  "description": "Lightweight, data-focused HTML/CSS admin framework built with PureCSS foundation and comprehensive component system",
5
5
  "style": "dist/css/main.css",
6
6
  "exports": {
@@ -259,6 +259,89 @@ async function main() {
259
259
  }
260
260
 
261
261
  console.log(`\nDownloaded ${downloaded} theme(s), skipped ${localThemes.length} local path(s)`);
262
+
263
+ // Check compatibility with installed core version
264
+ checkCoreCompatibility();
265
+ }
266
+
267
+ /**
268
+ * Check if downloaded themes are compatible with the installed core version
269
+ */
270
+ function checkCoreCompatibility() {
271
+ // Find installed core version
272
+ const corePkgPaths = [
273
+ path.join(PROJECT_ROOT, 'node_modules', '@keenmate', 'pure-admin-core', 'package.json'),
274
+ path.join(PROJECT_ROOT, '..', 'packages', 'core', 'package.json') // workspace
275
+ ];
276
+
277
+ let coreVersion = null;
278
+ for (const p of corePkgPaths) {
279
+ if (fs.existsSync(p)) {
280
+ try {
281
+ const pkg = JSON.parse(fs.readFileSync(p, 'utf-8'));
282
+ coreVersion = pkg.version;
283
+ break;
284
+ } catch (e) {}
285
+ }
286
+ }
287
+
288
+ if (!coreVersion) return;
289
+
290
+ // Check each downloaded theme
291
+ const warnings = [];
292
+ const themeDirs = fs.readdirSync(THEMES_DIR, { withFileTypes: true })
293
+ .filter(d => d.isDirectory())
294
+ .map(d => d.name);
295
+
296
+ for (const name of themeDirs) {
297
+ const manifestPath = path.join(THEMES_DIR, name, 'theme.json');
298
+ if (!fs.existsSync(manifestPath)) continue;
299
+
300
+ try {
301
+ const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
302
+ const requiredCore = manifest.dependencies && manifest.dependencies.core;
303
+ if (!requiredCore) continue;
304
+
305
+ if (!satisfiesSemver(coreVersion, requiredCore)) {
306
+ warnings.push(` ${name} (v${manifest.version}) requires core ${requiredCore}, installed: ${coreVersion}`);
307
+ }
308
+ } catch (e) {}
309
+ }
310
+
311
+ if (warnings.length > 0) {
312
+ console.log('\n⚠ Compatibility warnings:');
313
+ warnings.forEach(w => console.log(w));
314
+ console.log('\nConsider updating @keenmate/pure-admin-core');
315
+ } else if (themeDirs.length > 0) {
316
+ console.log(`\nAll themes compatible with core v${coreVersion}`);
317
+ }
318
+ }
319
+
320
+ /**
321
+ * Simple semver satisfaction check for ^major.minor.patch ranges
322
+ */
323
+ function satisfiesSemver(version, range) {
324
+ // Parse version
325
+ const v = version.replace(/^v/, '').split('.').map(Number);
326
+
327
+ // Parse range (supports ^x.y.z and x.y.z)
328
+ const caret = range.startsWith('^');
329
+ const r = range.replace(/^[\^~]/, '').split('.').map(Number);
330
+
331
+ if (caret) {
332
+ // ^2.0.0 means >=2.0.0 <3.0.0
333
+ // ^0.2.0 means >=0.2.0 <0.3.0
334
+ if (r[0] > 0) {
335
+ return v[0] === r[0] && (v[1] > r[1] || (v[1] === r[1] && v[2] >= r[2]));
336
+ } else if (r[1] > 0) {
337
+ return v[0] === 0 && v[1] === r[1] && v[2] >= r[2];
338
+ } else {
339
+ return v[0] === 0 && v[1] === 0 && v[2] === r[2];
340
+ }
341
+ }
342
+
343
+ // Exact match
344
+ return v[0] === r[0] && v[1] === r[1] && v[2] === r[2];
262
345
  }
263
346
 
264
347
  console.log('Downloading themes...\n');
@@ -1,37 +1,37 @@
1
- /* Pure Admin Visual Framework - Default Font Definitions */
2
-
3
- // Default framework fonts - themes can override these
4
- // Note: Font size classes for <html> are in _utilities.scss (use px values for correct rem scaling)
5
-
6
- // Font family classes with system defaults
7
- .font-family-system {
8
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
9
-
10
- *, h1, h2, h3, h4, h5, h6, p, div, span, button, input, textarea, select {
11
- font-family: inherit;
12
- }
13
- }
14
-
15
- .font-family-sans {
16
- font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
17
-
18
- *, h1, h2, h3, h4, h5, h6, p, div, span, button, input, textarea, select {
19
- font-family: inherit;
20
- }
21
- }
22
-
23
- .font-family-serif {
24
- font-family: Georgia, "Times New Roman", Times, serif;
25
-
26
- *, h1, h2, h3, h4, h5, h6, p, div, span, button, input, textarea, select {
27
- font-family: inherit;
28
- }
29
- }
30
-
31
- .font-family-mono {
32
- font-family: "Courier New", Courier, monospace;
33
-
34
- *, h1, h2, h3, h4, h5, h6, p, div, span, button, input, textarea, select {
35
- font-family: inherit;
36
- }
1
+ /* Pure Admin Visual Framework - Default Font Definitions */
2
+
3
+ // Default framework fonts - themes can override these
4
+ // Note: Font size classes for <html> are in _utilities.scss (use px values for correct rem scaling)
5
+
6
+ // Font family classes with system defaults
7
+ .font-family-system {
8
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
9
+
10
+ *, h1, h2, h3, h4, h5, h6, p, div, span, button, input, textarea, select {
11
+ font-family: inherit;
12
+ }
13
+ }
14
+
15
+ .font-family-sans {
16
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
17
+
18
+ *, h1, h2, h3, h4, h5, h6, p, div, span, button, input, textarea, select {
19
+ font-family: inherit;
20
+ }
21
+ }
22
+
23
+ .font-family-serif {
24
+ font-family: Georgia, "Times New Roman", Times, serif;
25
+
26
+ *, h1, h2, h3, h4, h5, h6, p, div, span, button, input, textarea, select {
27
+ font-family: inherit;
28
+ }
29
+ }
30
+
31
+ .font-family-mono {
32
+ font-family: "Courier New", Courier, monospace;
33
+
34
+ *, h1, h2, h3, h4, h5, h6, p, div, span, button, input, textarea, select {
35
+ font-family: inherit;
36
+ }
37
37
  }
@@ -1,362 +1,362 @@
1
- /* ========================================
2
- Utility Components
3
- Font utilities, compact mode, component showcase
4
- ======================================== */
5
- @use '../variables' as *;
6
-
7
- // Font size classes - Apply to <html> element for proportional scaling of all rem units
8
- // These use absolute px values because rem would be calculated against browser default (16px),
9
- // not the framework's 10px base. Scaling the html font-size scales all rem values proportionally.
10
- // Example: document.documentElement.classList.add('font-size-large');
11
-
12
- html.font-size-small {
13
- font-size: 9px; // ~14px body text (9 * 1.6 = 14.4px)
14
- }
15
-
16
- html.font-size-default {
17
- font-size: 10px; // 16px body text (default, same as html base)
18
- }
19
-
20
- html.font-size-large {
21
- font-size: 11px; // ~18px body text (11 * 1.6 = 17.6px)
22
- }
23
-
24
- html.font-size-xlarge {
25
- font-size: 12px; // ~19px body text (12 * 1.6 = 19.2px)
26
- }
27
-
28
- // Font family utilities
29
- // Only for overriding the theme's default font
30
- .font-family-serif {
31
- font-family: $font-stack-serif;
32
- }
33
-
34
- .font-family-mono {
35
- font-family: $font-stack-mono;
36
- }
37
-
38
- // Compact mode
39
- .compact-mode {
40
- .pa-card__body {
41
- padding: $spacing-md;
42
- }
43
-
44
- .pa-table td,
45
- .pa-table th {
46
- padding: $btn-padding-v $btn-padding-h;
47
- }
48
-
49
- .pa-sidebar__nav ul li a {
50
- padding: $sidebar-padding;
51
- }
52
-
53
- .pa-form-group {
54
- margin-bottom: $form-group-margin-compact;
55
- }
56
- }
57
-
58
-
59
- // Min-height utilities (rem-based)
60
- .min-h-2x { min-height: 2rem; } // 32px
61
- .min-h-3x { min-height: 3rem; } // 48px
62
- .min-h-5x { min-height: 5rem; } // 80px
63
- .min-h-8x { min-height: 8rem; } // 128px
64
- .min-h-10x { min-height: 10rem; } // 160px
65
- .min-h-12x { min-height: 12rem; } // 192px
66
- .min-h-15x { min-height: 15rem; } // 240px
67
- .min-h-20x { min-height: 20rem; } // 320px
68
- .min-h-25x { min-height: 25rem; } // 400px
69
- .min-h-30x { min-height: 30rem; } // 480px
70
-
71
- // Fixed height utilities (rem-based) - for scrollable containers
72
- .h-2x { height: 2rem; } // 32px
73
- .h-3x { height: 3rem; } // 48px
74
- .h-5x { height: 5rem; } // 80px
75
- .h-8x { height: 8rem; } // 128px
76
- .h-10x { height: 10rem; } // 160px
77
- .h-12x { height: 12rem; } // 192px
78
- .h-15x { height: 15rem; } // 240px
79
- .h-20x { height: 20rem; } // 320px
80
- .h-25x { height: 25rem; } // 400px
81
- .h-30x { height: 30rem; } // 480px
82
- .h-40x { height: 40rem; } // 640px
83
- .h-50x { height: 50rem; } // 800px
84
-
85
- // Max-height utilities (rem-based) - useful for limiting content height
86
- .max-h-5x { max-height: 5rem; } // 80px
87
- .max-h-8x { max-height: 8rem; } // 128px
88
- .max-h-10x { max-height: 10rem; } // 160px
89
- .max-h-12x { max-height: 12rem; } // 192px
90
- .max-h-15x { max-height: 15rem; } // 240px
91
- .max-h-20x { max-height: 20rem; } // 320px
92
- .max-h-25x { max-height: 25rem; } // 400px
93
- .max-h-30x { max-height: 30rem; } // 480px
94
- .max-h-40x { max-height: 40rem; } // 640px
95
- .max-h-50x { max-height: 50rem; } // 800px
96
-
97
- // Percentage-based height utilities - for filling available space
98
- .h-full { height: 100%; }
99
- .h-screen { height: 100vh; }
100
- .min-h-full { min-height: 100%; }
101
- .min-h-screen { min-height: 100vh; }
102
- .max-h-full { max-height: 100%; }
103
- .max-h-screen { max-height: 100vh; }
104
-
105
- // Flex utilities - for filling available space in flex containers
106
- .flex-1 { flex: 1 1 0%; } // Grow and shrink equally, ignore content size
107
- .flex-auto { flex: 1 1 auto; } // Grow and shrink, based on content size
108
- .flex-initial { flex: 0 1 auto; } // Shrink but don't grow (default)
109
- .flex-none { flex: none; } // Don't grow or shrink
110
- .flex-grow { flex-grow: 1; } // Grow to fill space
111
- .flex-grow-0 { flex-grow: 0; } // Don't grow
112
- .flex-shrink { flex-shrink: 1; } // Allow shrinking
113
- .flex-shrink-0 { flex-shrink: 0; } // Don't shrink
114
-
115
- // Overflow utilities - pair with height/max-height for scrollable content
116
- .overflow-auto { overflow: auto; }
117
- .overflow-y-auto { overflow-y: auto; }
118
- .overflow-x-auto { overflow-x: auto; }
119
- .overflow-hidden { overflow: hidden; }
120
- .overflow-visible { overflow: visible; }
121
-
122
- // Overlay scrollbar utilities (scrollbar floats over content, doesn't reduce width)
123
- // Supported in Chromium browsers; Firefox falls back to auto
124
- .overflow-overlay {
125
- overflow: auto;
126
- overflow: overlay;
127
- }
128
-
129
- .overflow-y-overlay {
130
- overflow-y: auto;
131
- overflow-y: overlay;
132
- }
133
-
134
- .overflow-x-overlay {
135
- overflow-x: auto;
136
- overflow-x: overlay;
137
- }
138
-
139
- // Scroll lock - prevents body scrolling when overlays are open
140
- // Apply to <body> element via JavaScript
141
- .pa-scroll-lock {
142
- overflow: hidden !important;
143
- }
144
-
145
- // Cursor utilities
146
- .cursor-pointer { cursor: pointer; }
147
- .cursor-help { cursor: help; }
148
- .cursor-wait { cursor: wait; }
149
- .cursor-not-allowed { cursor: not-allowed; }
150
- .cursor-text { cursor: text; }
151
- .cursor-move { cursor: move; }
152
- .cursor-default { cursor: default; }
153
- .cursor-grab { cursor: grab; }
154
- .cursor-grabbing { cursor: grabbing; }
155
- .cursor-zoom-in { cursor: zoom-in; }
156
- .cursor-zoom-out { cursor: zoom-out; }
157
-
158
- // ========================================
159
- // Text Component (BEM pattern)
160
- // For paragraph typography across pages
161
- // ========================================
162
- .pa-text {
163
- font-size: $font-size-sm; // 1.4rem (14px) - default
164
- color: var(--pa-text-color-1);
165
-
166
- // Size modifiers
167
- &--xs {
168
- font-size: $font-size-2xs; // 1rem (10px)
169
- }
170
-
171
- &--sm {
172
- font-size: $font-size-xs; // 1.2rem (12px)
173
- }
174
-
175
- &--lg {
176
- font-size: $font-size-base; // 1.6rem (16px)
177
- }
178
-
179
- &--xl {
180
- font-size: $font-size-lg; // 1.8rem (18px)
181
- }
182
-
183
- // Color modifiers
184
- &--primary {
185
- color: var(--pa-text-color-1);
186
- }
187
-
188
- &--secondary {
189
- color: var(--pa-text-color-2);
190
- }
191
-
192
- // Alignment modifiers (logical properties for RTL support)
193
- &--start {
194
- text-align: start; // RTL: flips to right
195
- }
196
-
197
- &--center {
198
- text-align: center;
199
- }
200
-
201
- &--end {
202
- text-align: end; // RTL: flips to left
203
- }
204
-
205
-
206
- // Semantic variants (compound styles)
207
- &--caption {
208
- font-size: $font-size-xs;
209
- color: var(--pa-text-color-2);
210
- margin-bottom: $spacing-sm;
211
- }
212
-
213
- &--lead {
214
- font-size: $font-size-base;
215
- line-height: $line-height-relaxed;
216
- }
217
- }
218
-
219
- // Gap utilities (10px rem base)
220
- // Semantic gap classes using spacing variables
221
- @each $name, $value in $semantic-spacers {
222
- .gap-#{$name} { gap: #{$value}; }
223
- .row-gap-#{$name} { row-gap: #{$value}; }
224
- .column-gap-#{$name} { column-gap: #{$value}; }
225
- }
226
-
227
- // Numeric gap classes (in 10px rem units) - kept for backwards compatibility
228
- .gap-1 { gap: 0.1rem; } // 1px
229
- .gap-2 { gap: 0.2rem; } // 2px
230
- .gap-3 { gap: 0.3rem; } // 3px
231
- .gap-4 { gap: 0.4rem; } // 4px
232
- .gap-5 { gap: 0.5rem; } // 5px
233
- .gap-6 { gap: 0.6rem; } // 6px
234
- .gap-8 { gap: 0.8rem; } // 8px
235
- .gap-10 { gap: 1rem; } // 10px
236
- .gap-12 { gap: 1.2rem; } // 12px
237
- .gap-15 { gap: 1.5rem; } // 15px
238
- .gap-20 { gap: 2rem; } // 20px
239
-
240
- // Align-self utilities (for flex/grid children)
241
- .self-start { align-self: flex-start; }
242
- .self-center { align-self: center; }
243
- .self-end { align-self: flex-end; }
244
- .self-stretch { align-self: stretch; }
245
- .self-baseline { align-self: baseline; }
246
-
247
- // Font-size utilities (10px rem base)
248
- // Direct font-size classes using typography variables
249
- .text-2xs { font-size: $font-size-2xs; } // 1rem = 10px
250
- .text-xs { font-size: $font-size-xs; } // 1.2rem = 12px
251
- .text-sm { font-size: $font-size-sm; } // 1.4rem = 14px
252
- .text-md { font-size: $font-size-md; } // 1.5rem = 15px
253
- .text-base { font-size: $font-size-base; } // 1.6rem = 16px
254
- .text-lg { font-size: $font-size-lg; } // 1.8rem = 18px
255
- .text-xl { font-size: $font-size-xl; } // 2rem = 20px
256
- .text-2xl { font-size: $font-size-2xl; } // 2.4rem = 24px
257
- .text-3xl { font-size: $font-size-3xl; } // 2.8rem = 28px
258
- .text-4xl { font-size: $font-size-4xl; } // 3.2rem = 32px
259
-
260
- // Text truncation with ellipsis
261
- .text-truncate {
262
- overflow: hidden;
263
- text-overflow: ellipsis;
264
- white-space: nowrap;
265
- }
266
-
267
- // Link styling
268
- .pa-link {
269
- color: $accent-color;
270
- text-decoration: none;
271
-
272
- &:hover {
273
- text-decoration: underline;
274
- }
275
- }
276
-
277
- // Component showcase styling
278
- .component-showcase {
279
- display: flex;
280
- flex-wrap: wrap;
281
- gap: $spacing-sm;
282
- margin-bottom: $spacing-lg;
283
- }
284
-
285
- // Usage example styling
286
- .usage-example {
287
- .user-item,
288
- .project-item {
289
- display: flex;
290
- align-items: center;
291
- justify-content: space-between;
292
- padding: $spacing-md;
293
- margin-bottom: $spacing-sm;
294
- background-color: var(--pa-card-bg);
295
- border: $border-width-base solid var(--pa-border-color);
296
- border-radius: $border-radius;
297
-
298
- .user-name {
299
- font-weight: $font-weight-medium;
300
- }
301
-
302
- h5 {
303
- margin: 0 0 $spacing-sm 0;
304
- font-size: $font-size-base;
305
- font-weight: $font-weight-semibold;
306
- }
307
-
308
- .project-tags {
309
- display: flex;
310
- flex-wrap: wrap;
311
- gap: $spacing-xs;
312
- }
313
- }
314
-
315
- .project-item {
316
- flex-direction: column;
317
- align-items: flex-start;
318
- }
319
- }
320
-
321
- // Theme color utilities (color-1 through color-9)
322
- // Use these to apply theme colors to any element
323
- @for $i from 1 through 9 {
324
- .pa-bg-color-#{$i} { background-color: var(--pa-color-#{$i}); }
325
- .pa-text-color-#{$i} { color: var(--pa-color-#{$i}); }
326
- .pa-border-color-#{$i} { border-color: var(--pa-color-#{$i}); }
327
- }
328
-
329
- // ========================================
330
- // Logical Spacing Utilities (RTL-aware)
331
- // ms = margin-inline-start, me = margin-inline-end
332
- // ps = padding-inline-start, pe = padding-inline-end
333
- // ========================================
334
-
335
- // Margin inline-start (ms-*) - RTL: flips to margin-right
336
- @each $name, $value in $semantic-spacers {
337
- .ms-#{$name} { margin-inline-start: #{$value}; }
338
- }
339
- .ms-auto { margin-inline-start: auto; }
340
-
341
- // Margin inline-end (me-*) - RTL: flips to margin-left
342
- @each $name, $value in $semantic-spacers {
343
- .me-#{$name} { margin-inline-end: #{$value}; }
344
- }
345
- .me-auto { margin-inline-end: auto; }
346
-
347
- // Padding inline-start (ps-*) - RTL: flips to padding-right
348
- @each $name, $value in $semantic-spacers {
349
- .ps-#{$name} { padding-inline-start: #{$value}; }
350
- }
351
-
352
- // Padding inline-end (pe-*) - RTL: flips to padding-left
353
- @each $name, $value in $semantic-spacers {
354
- .pe-#{$name} { padding-inline-end: #{$value}; }
355
- }
356
-
357
- // Text alignment utilities (RTL-aware)
358
- .text-start { text-align: start; } // RTL: flips to right
359
- .text-center { text-align: center; }
360
- .text-end { text-align: end; } // RTL: flips to left
361
-
362
-
1
+ /* ========================================
2
+ Utility Components
3
+ Font utilities, compact mode, component showcase
4
+ ======================================== */
5
+ @use '../variables' as *;
6
+
7
+ // Font size classes - Apply to <html> element for proportional scaling of all rem units
8
+ // These use absolute px values because rem would be calculated against browser default (16px),
9
+ // not the framework's 10px base. Scaling the html font-size scales all rem values proportionally.
10
+ // Example: document.documentElement.classList.add('font-size-large');
11
+
12
+ html.font-size-small {
13
+ font-size: 9px; // ~14px body text (9 * 1.6 = 14.4px)
14
+ }
15
+
16
+ html.font-size-default {
17
+ font-size: 10px; // 16px body text (default, same as html base)
18
+ }
19
+
20
+ html.font-size-large {
21
+ font-size: 11px; // ~18px body text (11 * 1.6 = 17.6px)
22
+ }
23
+
24
+ html.font-size-xlarge {
25
+ font-size: 12px; // ~19px body text (12 * 1.6 = 19.2px)
26
+ }
27
+
28
+ // Font family utilities
29
+ // Only for overriding the theme's default font
30
+ .font-family-serif {
31
+ font-family: $font-stack-serif;
32
+ }
33
+
34
+ .font-family-mono {
35
+ font-family: $font-stack-mono;
36
+ }
37
+
38
+ // Compact mode
39
+ .compact-mode {
40
+ .pa-card__body {
41
+ padding: $spacing-md;
42
+ }
43
+
44
+ .pa-table td,
45
+ .pa-table th {
46
+ padding: $btn-padding-v $btn-padding-h;
47
+ }
48
+
49
+ .pa-sidebar__nav ul li a {
50
+ padding: $sidebar-padding;
51
+ }
52
+
53
+ .pa-form-group {
54
+ margin-bottom: $form-group-margin-compact;
55
+ }
56
+ }
57
+
58
+
59
+ // Min-height utilities (rem-based)
60
+ .min-h-2x { min-height: 2rem; } // 32px
61
+ .min-h-3x { min-height: 3rem; } // 48px
62
+ .min-h-5x { min-height: 5rem; } // 80px
63
+ .min-h-8x { min-height: 8rem; } // 128px
64
+ .min-h-10x { min-height: 10rem; } // 160px
65
+ .min-h-12x { min-height: 12rem; } // 192px
66
+ .min-h-15x { min-height: 15rem; } // 240px
67
+ .min-h-20x { min-height: 20rem; } // 320px
68
+ .min-h-25x { min-height: 25rem; } // 400px
69
+ .min-h-30x { min-height: 30rem; } // 480px
70
+
71
+ // Fixed height utilities (rem-based) - for scrollable containers
72
+ .h-2x { height: 2rem; } // 32px
73
+ .h-3x { height: 3rem; } // 48px
74
+ .h-5x { height: 5rem; } // 80px
75
+ .h-8x { height: 8rem; } // 128px
76
+ .h-10x { height: 10rem; } // 160px
77
+ .h-12x { height: 12rem; } // 192px
78
+ .h-15x { height: 15rem; } // 240px
79
+ .h-20x { height: 20rem; } // 320px
80
+ .h-25x { height: 25rem; } // 400px
81
+ .h-30x { height: 30rem; } // 480px
82
+ .h-40x { height: 40rem; } // 640px
83
+ .h-50x { height: 50rem; } // 800px
84
+
85
+ // Max-height utilities (rem-based) - useful for limiting content height
86
+ .max-h-5x { max-height: 5rem; } // 80px
87
+ .max-h-8x { max-height: 8rem; } // 128px
88
+ .max-h-10x { max-height: 10rem; } // 160px
89
+ .max-h-12x { max-height: 12rem; } // 192px
90
+ .max-h-15x { max-height: 15rem; } // 240px
91
+ .max-h-20x { max-height: 20rem; } // 320px
92
+ .max-h-25x { max-height: 25rem; } // 400px
93
+ .max-h-30x { max-height: 30rem; } // 480px
94
+ .max-h-40x { max-height: 40rem; } // 640px
95
+ .max-h-50x { max-height: 50rem; } // 800px
96
+
97
+ // Percentage-based height utilities - for filling available space
98
+ .h-full { height: 100%; }
99
+ .h-screen { height: 100vh; }
100
+ .min-h-full { min-height: 100%; }
101
+ .min-h-screen { min-height: 100vh; }
102
+ .max-h-full { max-height: 100%; }
103
+ .max-h-screen { max-height: 100vh; }
104
+
105
+ // Flex utilities - for filling available space in flex containers
106
+ .flex-1 { flex: 1 1 0%; } // Grow and shrink equally, ignore content size
107
+ .flex-auto { flex: 1 1 auto; } // Grow and shrink, based on content size
108
+ .flex-initial { flex: 0 1 auto; } // Shrink but don't grow (default)
109
+ .flex-none { flex: none; } // Don't grow or shrink
110
+ .flex-grow { flex-grow: 1; } // Grow to fill space
111
+ .flex-grow-0 { flex-grow: 0; } // Don't grow
112
+ .flex-shrink { flex-shrink: 1; } // Allow shrinking
113
+ .flex-shrink-0 { flex-shrink: 0; } // Don't shrink
114
+
115
+ // Overflow utilities - pair with height/max-height for scrollable content
116
+ .overflow-auto { overflow: auto; }
117
+ .overflow-y-auto { overflow-y: auto; }
118
+ .overflow-x-auto { overflow-x: auto; }
119
+ .overflow-hidden { overflow: hidden; }
120
+ .overflow-visible { overflow: visible; }
121
+
122
+ // Overlay scrollbar utilities (scrollbar floats over content, doesn't reduce width)
123
+ // Supported in Chromium browsers; Firefox falls back to auto
124
+ .overflow-overlay {
125
+ overflow: auto;
126
+ overflow: overlay;
127
+ }
128
+
129
+ .overflow-y-overlay {
130
+ overflow-y: auto;
131
+ overflow-y: overlay;
132
+ }
133
+
134
+ .overflow-x-overlay {
135
+ overflow-x: auto;
136
+ overflow-x: overlay;
137
+ }
138
+
139
+ // Scroll lock - prevents body scrolling when overlays are open
140
+ // Apply to <body> element via JavaScript
141
+ .pa-scroll-lock {
142
+ overflow: hidden !important;
143
+ }
144
+
145
+ // Cursor utilities
146
+ .cursor-pointer { cursor: pointer; }
147
+ .cursor-help { cursor: help; }
148
+ .cursor-wait { cursor: wait; }
149
+ .cursor-not-allowed { cursor: not-allowed; }
150
+ .cursor-text { cursor: text; }
151
+ .cursor-move { cursor: move; }
152
+ .cursor-default { cursor: default; }
153
+ .cursor-grab { cursor: grab; }
154
+ .cursor-grabbing { cursor: grabbing; }
155
+ .cursor-zoom-in { cursor: zoom-in; }
156
+ .cursor-zoom-out { cursor: zoom-out; }
157
+
158
+ // ========================================
159
+ // Text Component (BEM pattern)
160
+ // For paragraph typography across pages
161
+ // ========================================
162
+ .pa-text {
163
+ font-size: $font-size-sm; // 1.4rem (14px) - default
164
+ color: var(--pa-text-color-1);
165
+
166
+ // Size modifiers
167
+ &--xs {
168
+ font-size: $font-size-2xs; // 1rem (10px)
169
+ }
170
+
171
+ &--sm {
172
+ font-size: $font-size-xs; // 1.2rem (12px)
173
+ }
174
+
175
+ &--lg {
176
+ font-size: $font-size-base; // 1.6rem (16px)
177
+ }
178
+
179
+ &--xl {
180
+ font-size: $font-size-lg; // 1.8rem (18px)
181
+ }
182
+
183
+ // Color modifiers
184
+ &--primary {
185
+ color: var(--pa-text-color-1);
186
+ }
187
+
188
+ &--secondary {
189
+ color: var(--pa-text-color-2);
190
+ }
191
+
192
+ // Alignment modifiers (logical properties for RTL support)
193
+ &--start {
194
+ text-align: start; // RTL: flips to right
195
+ }
196
+
197
+ &--center {
198
+ text-align: center;
199
+ }
200
+
201
+ &--end {
202
+ text-align: end; // RTL: flips to left
203
+ }
204
+
205
+
206
+ // Semantic variants (compound styles)
207
+ &--caption {
208
+ font-size: $font-size-xs;
209
+ color: var(--pa-text-color-2);
210
+ margin-bottom: $spacing-sm;
211
+ }
212
+
213
+ &--lead {
214
+ font-size: $font-size-base;
215
+ line-height: $line-height-relaxed;
216
+ }
217
+ }
218
+
219
+ // Gap utilities (10px rem base)
220
+ // Semantic gap classes using spacing variables
221
+ @each $name, $value in $semantic-spacers {
222
+ .gap-#{$name} { gap: #{$value}; }
223
+ .row-gap-#{$name} { row-gap: #{$value}; }
224
+ .column-gap-#{$name} { column-gap: #{$value}; }
225
+ }
226
+
227
+ // Numeric gap classes (in 10px rem units) - kept for backwards compatibility
228
+ .gap-1 { gap: 0.1rem; } // 1px
229
+ .gap-2 { gap: 0.2rem; } // 2px
230
+ .gap-3 { gap: 0.3rem; } // 3px
231
+ .gap-4 { gap: 0.4rem; } // 4px
232
+ .gap-5 { gap: 0.5rem; } // 5px
233
+ .gap-6 { gap: 0.6rem; } // 6px
234
+ .gap-8 { gap: 0.8rem; } // 8px
235
+ .gap-10 { gap: 1rem; } // 10px
236
+ .gap-12 { gap: 1.2rem; } // 12px
237
+ .gap-15 { gap: 1.5rem; } // 15px
238
+ .gap-20 { gap: 2rem; } // 20px
239
+
240
+ // Align-self utilities (for flex/grid children)
241
+ .self-start { align-self: flex-start; }
242
+ .self-center { align-self: center; }
243
+ .self-end { align-self: flex-end; }
244
+ .self-stretch { align-self: stretch; }
245
+ .self-baseline { align-self: baseline; }
246
+
247
+ // Font-size utilities (10px rem base)
248
+ // Direct font-size classes using typography variables
249
+ .text-2xs { font-size: $font-size-2xs; } // 1rem = 10px
250
+ .text-xs { font-size: $font-size-xs; } // 1.2rem = 12px
251
+ .text-sm { font-size: $font-size-sm; } // 1.4rem = 14px
252
+ .text-md { font-size: $font-size-md; } // 1.5rem = 15px
253
+ .text-base { font-size: $font-size-base; } // 1.6rem = 16px
254
+ .text-lg { font-size: $font-size-lg; } // 1.8rem = 18px
255
+ .text-xl { font-size: $font-size-xl; } // 2rem = 20px
256
+ .text-2xl { font-size: $font-size-2xl; } // 2.4rem = 24px
257
+ .text-3xl { font-size: $font-size-3xl; } // 2.8rem = 28px
258
+ .text-4xl { font-size: $font-size-4xl; } // 3.2rem = 32px
259
+
260
+ // Text truncation with ellipsis
261
+ .text-truncate {
262
+ overflow: hidden;
263
+ text-overflow: ellipsis;
264
+ white-space: nowrap;
265
+ }
266
+
267
+ // Link styling
268
+ .pa-link {
269
+ color: $accent-color;
270
+ text-decoration: none;
271
+
272
+ &:hover {
273
+ text-decoration: underline;
274
+ }
275
+ }
276
+
277
+ // Component showcase styling
278
+ .component-showcase {
279
+ display: flex;
280
+ flex-wrap: wrap;
281
+ gap: $spacing-sm;
282
+ margin-bottom: $spacing-lg;
283
+ }
284
+
285
+ // Usage example styling
286
+ .usage-example {
287
+ .user-item,
288
+ .project-item {
289
+ display: flex;
290
+ align-items: center;
291
+ justify-content: space-between;
292
+ padding: $spacing-md;
293
+ margin-bottom: $spacing-sm;
294
+ background-color: var(--pa-card-bg);
295
+ border: $border-width-base solid var(--pa-border-color);
296
+ border-radius: $border-radius;
297
+
298
+ .user-name {
299
+ font-weight: $font-weight-medium;
300
+ }
301
+
302
+ h5 {
303
+ margin: 0 0 $spacing-sm 0;
304
+ font-size: $font-size-base;
305
+ font-weight: $font-weight-semibold;
306
+ }
307
+
308
+ .project-tags {
309
+ display: flex;
310
+ flex-wrap: wrap;
311
+ gap: $spacing-xs;
312
+ }
313
+ }
314
+
315
+ .project-item {
316
+ flex-direction: column;
317
+ align-items: flex-start;
318
+ }
319
+ }
320
+
321
+ // Theme color utilities (color-1 through color-9)
322
+ // Use these to apply theme colors to any element
323
+ @for $i from 1 through 9 {
324
+ .pa-bg-color-#{$i} { background-color: var(--pa-color-#{$i}); }
325
+ .pa-text-color-#{$i} { color: var(--pa-color-#{$i}); }
326
+ .pa-border-color-#{$i} { border-color: var(--pa-color-#{$i}); }
327
+ }
328
+
329
+ // ========================================
330
+ // Logical Spacing Utilities (RTL-aware)
331
+ // ms = margin-inline-start, me = margin-inline-end
332
+ // ps = padding-inline-start, pe = padding-inline-end
333
+ // ========================================
334
+
335
+ // Margin inline-start (ms-*) - RTL: flips to margin-right
336
+ @each $name, $value in $semantic-spacers {
337
+ .ms-#{$name} { margin-inline-start: #{$value}; }
338
+ }
339
+ .ms-auto { margin-inline-start: auto; }
340
+
341
+ // Margin inline-end (me-*) - RTL: flips to margin-left
342
+ @each $name, $value in $semantic-spacers {
343
+ .me-#{$name} { margin-inline-end: #{$value}; }
344
+ }
345
+ .me-auto { margin-inline-end: auto; }
346
+
347
+ // Padding inline-start (ps-*) - RTL: flips to padding-right
348
+ @each $name, $value in $semantic-spacers {
349
+ .ps-#{$name} { padding-inline-start: #{$value}; }
350
+ }
351
+
352
+ // Padding inline-end (pe-*) - RTL: flips to padding-left
353
+ @each $name, $value in $semantic-spacers {
354
+ .pe-#{$name} { padding-inline-end: #{$value}; }
355
+ }
356
+
357
+ // Text alignment utilities (RTL-aware)
358
+ .text-start { text-align: start; } // RTL: flips to right
359
+ .text-center { text-align: center; }
360
+ .text-end { text-align: end; } // RTL: flips to left
361
+
362
+
@@ -105,7 +105,7 @@ body.pa-layout--sticky .pa-layout__sidebar {
105
105
  }
106
106
 
107
107
  &--active {
108
- color: var(--pa-sidebar-text);
108
+ color: var(--pa-accent);
109
109
  background-color: var(--pa-accent-hover);
110
110
  border-inline-end-color: var(--pa-accent); // RTL: flips to border-left-color
111
111
  font-weight: $font-weight-semibold;
@@ -136,7 +136,7 @@ body.pa-layout--sticky .pa-layout__sidebar {
136
136
  }
137
137
 
138
138
  &--active {
139
- color: var(--pa-sidebar-text);
139
+ color: var(--pa-accent);
140
140
  background-color: var(--pa-accent-hover);
141
141
  }
142
142
  }