@keenmate/pure-admin-core 1.2.0 → 1.3.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keenmate/pure-admin-core",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
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": {
@@ -448,6 +448,7 @@
448
448
  // =========================================================================
449
449
  --pa-detail-panel-overlay-bg: #{$detail-panel-overlay-bg};
450
450
  --pa-detail-panel-selected-bg: #{$detail-panel-selected-bg};
451
+ --pa-detail-panel-z-index: #{$detail-panel-z-index};
451
452
 
452
453
  // =========================================================================
453
454
  // COMMAND PALETTE COLORS
@@ -104,5 +104,8 @@
104
104
  // Settings Panel
105
105
  @use 'core-components/settings-panel' as *;
106
106
 
107
+ // Data Display (read-only fields)
108
+ @use 'core-components/data-display' as *;
109
+
107
110
  // Utility classes and helpers
108
111
  @use 'core-components/utilities' as *;
@@ -0,0 +1,347 @@
1
+ /* ========================================
2
+ Data Display Components
3
+ Read-only label-value field pairs
4
+ ======================================== */
5
+ @use '../variables' as *;
6
+
7
+ // ============================================================================
8
+ // SINGLE FIELD (.pa-field)
9
+ // Default: stacked (label on top, value below)
10
+ // ============================================================================
11
+
12
+ .pa-field {
13
+ display: flex;
14
+ flex-direction: column;
15
+ gap: $field-gap;
16
+
17
+ &__label {
18
+ display: block;
19
+ font-size: $field-label-font-size;
20
+ font-weight: $field-label-font-weight;
21
+ opacity: $field-label-opacity;
22
+ line-height: $line-height-tight;
23
+ text-transform: uppercase;
24
+ letter-spacing: 0.05em;
25
+ }
26
+
27
+ &__value {
28
+ display: block;
29
+ font-size: $field-value-font-size;
30
+ font-weight: $font-weight-normal;
31
+ line-height: $line-height-base;
32
+ }
33
+
34
+ // Full-width modifier (spans entire row in grid layouts)
35
+ &--full {
36
+ grid-column: 1 / -1;
37
+ }
38
+
39
+ // ------------------------------------------------------------------
40
+ // COPYABLE: copy value to clipboard
41
+ // ------------------------------------------------------------------
42
+
43
+ // Copy button always visible
44
+ &--copy-btn {
45
+ .pa-field__value {
46
+ display: flex;
47
+ align-items: center;
48
+ gap: $spacing-sm;
49
+ }
50
+
51
+ .pa-field__copy {
52
+ flex-shrink: 0;
53
+ padding: 0.4rem;
54
+ background: transparent;
55
+ border: none;
56
+ border-radius: $border-radius;
57
+ cursor: pointer;
58
+ opacity: 0.5;
59
+ transition: opacity 0.15s, background 0.15s;
60
+
61
+ &:hover {
62
+ opacity: 1;
63
+ background: rgba(128, 128, 128, 0.1);
64
+ }
65
+ }
66
+ }
67
+
68
+ // Click value to copy
69
+ &--copy-click {
70
+ .pa-field__value {
71
+ cursor: pointer;
72
+ transition: opacity 0.15s;
73
+
74
+ &:hover {
75
+ opacity: 0.7;
76
+ }
77
+
78
+ &::after {
79
+ content: 'Click to copy';
80
+ font-size: $font-size-2xs;
81
+ opacity: 0;
82
+ margin-left: $spacing-sm;
83
+ transition: opacity 0.15s;
84
+ }
85
+
86
+ &:hover::after {
87
+ opacity: 0.6;
88
+ }
89
+ }
90
+ }
91
+
92
+ // Copy icon on hover only
93
+ &--copy-hover {
94
+ .pa-field__value {
95
+ display: flex;
96
+ align-items: center;
97
+ gap: $spacing-sm;
98
+ }
99
+
100
+ .pa-field__copy {
101
+ flex-shrink: 0;
102
+ padding: 0.4rem;
103
+ background: transparent;
104
+ border: none;
105
+ border-radius: $border-radius;
106
+ cursor: pointer;
107
+ opacity: 0;
108
+ transition: opacity 0.15s, background 0.15s;
109
+ }
110
+
111
+ &:hover .pa-field__copy {
112
+ opacity: 0.5;
113
+
114
+ &:hover {
115
+ opacity: 1;
116
+ background: rgba(128, 128, 128, 0.1);
117
+ }
118
+ }
119
+ }
120
+
121
+ // Copied feedback state
122
+ &--copied {
123
+ .pa-field__value::after {
124
+ content: 'Copied!' !important;
125
+ opacity: 1 !important;
126
+ color: var(--pa-color-4, #28a745);
127
+ }
128
+ }
129
+ }
130
+
131
+ // ============================================================================
132
+ // FIELD GROUP (.pa-field-group)
133
+ // Labeled section containing .pa-fields (e.g., "Customer", "Delivery Address")
134
+ // ============================================================================
135
+
136
+ .pa-field-group {
137
+ display: flex;
138
+ flex-direction: column;
139
+ gap: $field-group-gap;
140
+
141
+ &__title {
142
+ font-size: $field-group-title-font-size;
143
+ font-weight: $field-group-title-font-weight;
144
+ line-height: $line-height-tight;
145
+ padding-bottom: $spacing-xs;
146
+ border-bottom: $border-width-thin solid $field-group-title-border-color;
147
+ margin: 0;
148
+ }
149
+ }
150
+
151
+ // Vertical spacing between consecutive field groups
152
+ .pa-field-group + .pa-field-group {
153
+ margin-top: $field-group-spacing;
154
+ }
155
+
156
+ // Vertical spacing between consecutive pa-fields containers
157
+ .pa-fields + .pa-fields {
158
+ margin-top: $field-group-spacing;
159
+ }
160
+
161
+ // ============================================================================
162
+ // FIELD CONTAINER (.pa-fields)
163
+ // Container for multiple .pa-field items
164
+ // ============================================================================
165
+
166
+ .pa-fields {
167
+ display: flex;
168
+ flex-direction: column;
169
+ gap: $fields-gap;
170
+ border-left: $fields-border-left;
171
+ padding-left: $fields-padding-left;
172
+
173
+ // ------------------------------------------------------------------
174
+ // GRID COLUMNS: multi-column layouts using CSS grid
175
+ // ------------------------------------------------------------------
176
+ &--cols-2,
177
+ &--cols-3,
178
+ &--cols-4 {
179
+ display: grid;
180
+ gap: $fields-cols-gap $fields-cols-gap;
181
+ }
182
+
183
+ &--cols-2 { grid-template-columns: repeat(2, 1fr); }
184
+ &--cols-3 { grid-template-columns: repeat(3, 1fr); }
185
+ &--cols-4 { grid-template-columns: repeat(4, 1fr); }
186
+
187
+ @media (max-width: $mobile-breakpoint) {
188
+ &--cols-2,
189
+ &--cols-3,
190
+ &--cols-4 {
191
+ grid-template-columns: 1fr;
192
+ }
193
+ }
194
+
195
+ // ------------------------------------------------------------------
196
+ // HORIZONTAL: label left, value right (side-by-side)
197
+ // ------------------------------------------------------------------
198
+ &--horizontal {
199
+ .pa-field {
200
+ flex-direction: row;
201
+ align-items: baseline;
202
+ gap: $spacing-base;
203
+ }
204
+
205
+ .pa-field__label {
206
+ flex: 0 0 auto;
207
+ min-width: 8rem;
208
+ max-width: 40%;
209
+ }
210
+
211
+ .pa-field__value {
212
+ flex: 1;
213
+ min-width: 0;
214
+ }
215
+ }
216
+
217
+ // ------------------------------------------------------------------
218
+ // TABLE: consistent label widths, like a key-value table
219
+ // ------------------------------------------------------------------
220
+ &--table {
221
+ .pa-field {
222
+ flex-direction: row;
223
+ align-items: baseline;
224
+ gap: $spacing-base;
225
+ }
226
+
227
+ .pa-field__label {
228
+ flex: 0 0 auto;
229
+ min-width: 8rem;
230
+ max-width: 40%;
231
+ }
232
+
233
+ .pa-field__value {
234
+ flex: 1;
235
+ min-width: 0;
236
+ }
237
+ }
238
+
239
+ // ------------------------------------------------------------------
240
+ // BORDERED: bottom border separator between fields
241
+ // ------------------------------------------------------------------
242
+ &--bordered {
243
+ .pa-field {
244
+ padding-bottom: $fields-bordered-padding;
245
+ border-bottom: $border-width-thin solid $fields-bordered-border-color;
246
+ }
247
+
248
+ .pa-field:last-child {
249
+ border-bottom: none;
250
+ padding-bottom: 0;
251
+ }
252
+ }
253
+
254
+ // ------------------------------------------------------------------
255
+ // STRIPED: alternating background rows
256
+ // ------------------------------------------------------------------
257
+ &--striped {
258
+ .pa-field:nth-child(odd) {
259
+ background: var(--pa-table-stripe);
260
+ padding: $fields-bordered-padding;
261
+ border-radius: $border-radius;
262
+ }
263
+
264
+ .pa-field:nth-child(even) {
265
+ padding: $fields-bordered-padding;
266
+ }
267
+ }
268
+
269
+ // ------------------------------------------------------------------
270
+ // COMPACT: tighter spacing
271
+ // ------------------------------------------------------------------
272
+ &--compact {
273
+ gap: $spacing-xs;
274
+
275
+ .pa-field {
276
+ gap: $spacing-xs;
277
+ }
278
+ }
279
+
280
+ // ------------------------------------------------------------------
281
+ // INLINE: multiple fields flowing on one line
282
+ // ------------------------------------------------------------------
283
+ &--inline {
284
+ flex-direction: row;
285
+ flex-wrap: wrap;
286
+ gap: $spacing-base;
287
+
288
+ .pa-field {
289
+ flex: 0 0 auto;
290
+ }
291
+ }
292
+
293
+ // ------------------------------------------------------------------
294
+ // RELAXED: larger gap between fields
295
+ // ------------------------------------------------------------------
296
+ &--relaxed {
297
+ gap: $fields-relaxed-gap;
298
+ }
299
+
300
+ // ------------------------------------------------------------------
301
+ // ROW: equal-width columns (auto based on child count)
302
+ // ------------------------------------------------------------------
303
+ &--row {
304
+ flex-direction: row;
305
+
306
+ .pa-field {
307
+ flex: 1;
308
+ min-width: 0;
309
+ }
310
+
311
+ @media (max-width: $mobile-breakpoint) {
312
+ flex-direction: column;
313
+ }
314
+ }
315
+
316
+ // ------------------------------------------------------------------
317
+ // FILLED: subtle background panel
318
+ // ------------------------------------------------------------------
319
+ &--filled {
320
+ background: $fields-filled-bg;
321
+ padding: $fields-filled-padding;
322
+ border-radius: $border-radius;
323
+ }
324
+
325
+ // ------------------------------------------------------------------
326
+ // COLOR VARIANTS: theme colors for border and filled background
327
+ // Uses --pa-color-{1-9} CSS variables
328
+ // ------------------------------------------------------------------
329
+ @for $i from 1 through 9 {
330
+ &--color-#{$i} {
331
+ border-left-color: var(--pa-color-#{$i});
332
+
333
+ // When combined with --filled, tint the background
334
+ &.pa-fields--filled {
335
+ background: color-mix(in srgb, var(--pa-color-#{$i}) 10%, transparent);
336
+ }
337
+ }
338
+ }
339
+
340
+ // ------------------------------------------------------------------
341
+ // NO BORDER: remove left border
342
+ // ------------------------------------------------------------------
343
+ &--no-border {
344
+ border-left: none;
345
+ padding-left: 0;
346
+ }
347
+ }
@@ -99,7 +99,7 @@
99
99
  top: 0;
100
100
  right: 0;
101
101
  height: 100vh;
102
- z-index: $detail-panel-z-index;
102
+ z-index: var(--pa-detail-panel-z-index);
103
103
  pointer-events: none;
104
104
  opacity: 0;
105
105
  visibility: hidden;
@@ -296,7 +296,7 @@
296
296
  top: 0;
297
297
  right: 0;
298
298
  height: 100vh;
299
- z-index: $detail-panel-z-index;
299
+ z-index: var(--pa-detail-panel-z-index);
300
300
  pointer-events: none;
301
301
  opacity: 0;
302
302
  visibility: hidden;
@@ -173,6 +173,8 @@ $grid-columns-fractions: (
173
173
  .pa-col-#{$bp}-#{$size} {
174
174
  flex: 0 0 math.percentage(math.div($size, 100));
175
175
  max-width: math.percentage(math.div($size, 100));
176
+ padding-left: $grid-gutter;
177
+ padding-right: $grid-gutter;
176
178
  min-width: 0; // Prevent content overflow
177
179
  }
178
180
  }
@@ -182,6 +184,8 @@ $grid-columns-fractions: (
182
184
  .pa-col-#{$bp}-#{$name} {
183
185
  flex: 0 0 $width;
184
186
  max-width: $width;
187
+ padding-left: $grid-gutter;
188
+ padding-right: $grid-gutter;
185
189
  min-width: 0; // Prevent content overflow
186
190
  }
187
191
  }
@@ -13,6 +13,266 @@
13
13
  border-radius: $border-radius;
14
14
  border: $border-width-base solid var(--pa-border-color);
15
15
  background-color: var(--pa-table-bg);
16
+
17
+ // Panel modifier - card-like visual containment
18
+ &--panel {
19
+ box-shadow: $shadow-sm;
20
+ border-radius: $card-border-radius;
21
+ margin-bottom: $spacing-base;
22
+ transition: box-shadow $transition-fast $easing-snappy;
23
+
24
+ &:hover {
25
+ box-shadow: $shadow-lg;
26
+ }
27
+ }
28
+
29
+ // Header for panel tables
30
+ &__header {
31
+ display: flex;
32
+ align-items: center;
33
+ justify-content: space-between;
34
+ padding: $card-header-padding-v $card-header-padding-h;
35
+ min-height: $card-header-min-height;
36
+ border-bottom: $border-width-base solid var(--pa-border-color);
37
+ background: var(--pa-card-header-bg);
38
+ border-top-left-radius: $card-border-radius;
39
+ border-top-right-radius: $card-border-radius;
40
+ }
41
+
42
+ &__title {
43
+ font-size: $font-size-base;
44
+ font-weight: $font-weight-semibold;
45
+ margin: 0;
46
+ color: var(--pa-text-color-1);
47
+ }
48
+
49
+ &__actions {
50
+ display: flex;
51
+ align-items: center;
52
+ gap: $spacing-sm;
53
+
54
+ // Buttons in header - negative margin to prevent header height growth
55
+ .pa-btn {
56
+ margin-top: -0.25rem;
57
+ margin-bottom: -0.25rem;
58
+ }
59
+ }
60
+ }
61
+
62
+ // ============================================================================
63
+ // TABLE CARD
64
+ // Card-like container specifically designed for tables
65
+ // Similar to pa-card but with table as body content (no body padding)
66
+ // ============================================================================
67
+ .pa-table-card {
68
+ background: var(--pa-card-bg);
69
+ border: $card-border-width solid var(--pa-border-color);
70
+ border-radius: $card-border-radius;
71
+ margin-bottom: $spacing-base;
72
+ box-shadow: $shadow-sm;
73
+ transition: box-shadow $transition-fast $easing-snappy;
74
+ display: flex;
75
+ flex-direction: column;
76
+ overflow: hidden; // Ensure table respects border-radius
77
+
78
+ &:hover {
79
+ box-shadow: $shadow-lg;
80
+ }
81
+
82
+ &__header {
83
+ padding: $card-header-padding-v $card-header-padding-h;
84
+ min-height: $card-header-min-height;
85
+ border-top-left-radius: $card-border-radius;
86
+ border-top-right-radius: $card-border-radius;
87
+ border-bottom: $border-width-base solid var(--pa-border-color);
88
+ background: var(--pa-card-header-bg);
89
+ display: flex;
90
+ justify-content: space-between;
91
+ align-items: center;
92
+ min-width: 0;
93
+
94
+ h1, h2, h3, h4, h5, h6, p {
95
+ margin: 0;
96
+ padding: 0;
97
+ }
98
+
99
+ h1, h2, h3, h4, h5, h6 {
100
+ color: var(--pa-text-color-1);
101
+ font-size: $font-size-base;
102
+ font-weight: $font-weight-semibold;
103
+ }
104
+
105
+ .pa-btn {
106
+ margin-top: -0.25rem;
107
+ margin-bottom: -0.25rem;
108
+ }
109
+ }
110
+
111
+ &__title {
112
+ display: flex;
113
+ align-items: center;
114
+ gap: $spacing-sm;
115
+ min-width: 0;
116
+ flex: 1;
117
+
118
+ &-text {
119
+ overflow: hidden;
120
+ text-overflow: ellipsis;
121
+ white-space: nowrap;
122
+ margin: 0;
123
+ color: var(--pa-text-color-1);
124
+ font-size: $font-size-base;
125
+ font-weight: $font-weight-semibold;
126
+ line-height: 1;
127
+ }
128
+ }
129
+
130
+ &__actions {
131
+ display: flex;
132
+ gap: $spacing-sm;
133
+ align-items: center;
134
+ }
135
+
136
+ &__body {
137
+ flex: 1;
138
+ min-width: 0; // Allow body to shrink below content size for proper overflow
139
+
140
+ // Scrollable wrapper for tables (optional - use when table needs horizontal scroll)
141
+ &--scrollable {
142
+ overflow-x: auto;
143
+ }
144
+
145
+ // Table inside body
146
+ .pa-table {
147
+ border-radius: 0;
148
+
149
+ // Align first/last column with card header/footer padding
150
+ th:first-child,
151
+ td:first-child {
152
+ padding-left: $card-header-padding-h;
153
+ }
154
+
155
+ th:last-child,
156
+ td:last-child {
157
+ padding-right: $card-header-padding-h;
158
+ }
159
+
160
+ // Remove bottom border from last row (card border handles it)
161
+ tbody tr:last-child td {
162
+ border-bottom: none;
163
+ }
164
+ }
165
+ }
166
+
167
+ &__footer {
168
+ padding: $card-footer-padding-v $card-footer-padding-h;
169
+ border-top: $border-width-base solid var(--pa-border-color);
170
+ border-bottom-left-radius: $card-border-radius;
171
+ border-bottom-right-radius: $card-border-radius;
172
+ background: var(--pa-card-footer-bg);
173
+ display: flex;
174
+ justify-content: space-between;
175
+ align-items: center;
176
+ }
177
+
178
+ // Color variants
179
+ &--primary {
180
+ border-color: var(--pa-accent);
181
+
182
+ .pa-table-card__header {
183
+ background-color: var(--pa-accent);
184
+ color: var(--pa-btn-primary-text);
185
+
186
+ h1, h2, h3, h4, h5, h6 {
187
+ color: var(--pa-btn-primary-text);
188
+ }
189
+ }
190
+ }
191
+
192
+ &--success {
193
+ border-color: var(--pa-success-bg);
194
+
195
+ .pa-table-card__header {
196
+ background-color: var(--pa-success-bg);
197
+ color: var(--pa-btn-success-text);
198
+
199
+ h1, h2, h3, h4, h5, h6 {
200
+ color: var(--pa-btn-success-text);
201
+ }
202
+ }
203
+ }
204
+
205
+ &--warning {
206
+ border-color: var(--pa-warning-bg);
207
+
208
+ .pa-table-card__header {
209
+ background-color: var(--pa-warning-bg);
210
+ color: var(--pa-btn-warning-text);
211
+
212
+ h1, h2, h3, h4, h5, h6 {
213
+ color: var(--pa-btn-warning-text);
214
+ }
215
+ }
216
+ }
217
+
218
+ &--danger {
219
+ border-color: var(--pa-danger-bg);
220
+
221
+ .pa-table-card__header {
222
+ background-color: var(--pa-danger-bg);
223
+ color: var(--pa-btn-danger-text);
224
+
225
+ h1, h2, h3, h4, h5, h6 {
226
+ color: var(--pa-btn-danger-text);
227
+ }
228
+ }
229
+ }
230
+
231
+ // Theme color variants (color-1 through color-9)
232
+ @for $i from 1 through 9 {
233
+ &--color-#{$i} {
234
+ border-color: var(--pa-color-#{$i});
235
+
236
+ .pa-table-card__header {
237
+ background-color: var(--pa-color-#{$i});
238
+ color: var(--pa-color-#{$i}-text);
239
+
240
+ h1, h2, h3, h4, h5, h6 {
241
+ color: var(--pa-color-#{$i}-text);
242
+ }
243
+ }
244
+ }
245
+ }
246
+
247
+ // Plain variant - no card visual styling, just layout structure
248
+ &--plain {
249
+ background: transparent;
250
+ border: none;
251
+ box-shadow: none;
252
+ border-radius: 0;
253
+
254
+ &:hover {
255
+ box-shadow: none;
256
+ }
257
+
258
+ // Header in plain mode - simple text header without card styling
259
+ .pa-table-card__header {
260
+ background: transparent;
261
+ border-bottom: none;
262
+ border-radius: 0;
263
+ padding-left: 0;
264
+ padding-right: 0;
265
+ }
266
+
267
+ // Footer in plain mode
268
+ .pa-table-card__footer {
269
+ background: transparent;
270
+ border-top: none;
271
+ border-radius: 0;
272
+ padding-left: 0;
273
+ padding-right: 0;
274
+ }
275
+ }
16
276
  }
17
277
 
18
278
  .pa-table {
@@ -63,6 +323,23 @@
63
323
  }
64
324
  }
65
325
 
326
+ // Bordered variant - full cell borders
327
+ &--bordered {
328
+ border: $border-width-base solid var(--pa-border-color);
329
+
330
+ th,
331
+ td {
332
+ border: $border-width-base solid var(--pa-border-color);
333
+ }
334
+
335
+ // Keep last row border in bordered mode
336
+ &:not(&--responsive) {
337
+ tbody tr:last-child td {
338
+ border-bottom: $border-width-base solid var(--pa-border-color);
339
+ }
340
+ }
341
+ }
342
+
66
343
  // Size variants - synchronized with button/input sizes
67
344
  &--xs {
68
345
  th, td {