@cratis/components 4.10.4 → 4.11.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.
@@ -0,0 +1,559 @@
1
+ @layer cratis-components {
2
+ /* @cratis/components/Filter/styles — requires @cratis/components/styles/base. Areas: Filter. */
3
+ /* ── ./Filter/FilterPanel.css ─────────────────────────────────────── */
4
+ /* -----------------------------------------------------------------------
5
+ * Standalone FilterPanel styles.
6
+ *
7
+ * These styles are shared by the standalone FilterPanel component and the
8
+ * PivotViewer which embeds it. All class names use the .pv-filter-* prefix
9
+ * so they can coexist with PivotViewer's other .pv-* rules.
10
+ * ----------------------------------------------------------------------- */
11
+
12
+ .pv-filter-panel {
13
+ position: fixed;
14
+ width: min(280px, calc(100% - 2rem));
15
+ max-height: calc(100vh - 6.5rem);
16
+ background: linear-gradient(
17
+ 180deg,
18
+ var(--cratis-surface-card),
19
+ var(--cratis-surface-ground)
20
+ );
21
+ border: 1px solid var(--cratis-surface-border);
22
+ border-radius: 1rem;
23
+ box-shadow: 0 24px 60px rgba(0, 0, 0, 0.3);
24
+ backdrop-filter: blur(14px);
25
+ overflow: hidden;
26
+ z-index: 12;
27
+ display: flex;
28
+ flex-direction: column;
29
+ }
30
+
31
+ .pv-filter-panel.dragging {
32
+ cursor: grabbing;
33
+ user-select: none;
34
+ }
35
+
36
+ .pv-filter-panel.minimized {
37
+ max-height: none;
38
+ }
39
+
40
+ .pv-filter-panel-header {
41
+ display: flex;
42
+ align-items: center;
43
+ gap: 0.5rem;
44
+ padding: 0.75rem 1rem;
45
+ cursor: grab;
46
+ background: var(--cratis-surface-section);
47
+ border-bottom: 1px solid var(--cratis-surface-border);
48
+ flex-shrink: 0;
49
+ }
50
+
51
+ .pv-filter-panel.dragging .pv-filter-panel-header {
52
+ cursor: grabbing;
53
+ }
54
+
55
+ .pv-filter-panel-header h2 {
56
+ margin: 0;
57
+ font-size: 0.85rem;
58
+ letter-spacing: 0.04em;
59
+ text-transform: uppercase;
60
+ color: var(--cratis-text-color);
61
+ flex: 1;
62
+ pointer-events: none;
63
+ }
64
+
65
+ .pv-minimize-btn,
66
+ .pv-close-btn {
67
+ appearance: none;
68
+ border: none;
69
+ border-radius: 0.4rem;
70
+ width: 1.5rem;
71
+ height: 1.5rem;
72
+ display: flex;
73
+ align-items: center;
74
+ justify-content: center;
75
+ background: var(--cratis-highlight-bg);
76
+ color: var(--cratis-text-color);
77
+ font-size: 1rem;
78
+ font-weight: 500;
79
+ cursor: pointer;
80
+ transition: background 120ms ease;
81
+ }
82
+
83
+ .pv-minimize-btn:hover,
84
+ .pv-close-btn:hover {
85
+ background: var(--cratis-surface-hover);
86
+ }
87
+
88
+ .pv-close-btn {
89
+ font-size: 1.2rem;
90
+ }
91
+
92
+ .pv-filter-panel-content {
93
+ overflow: hidden;
94
+ max-height: 0;
95
+ opacity: 0;
96
+ padding: 0 1.25rem;
97
+ transition:
98
+ max-height 150ms ease-out,
99
+ opacity 100ms ease-out,
100
+ padding 150ms ease-out;
101
+ }
102
+
103
+ .pv-filter-panel-content.expanded {
104
+ overflow-y: auto;
105
+ flex: 1;
106
+ max-height: 600px;
107
+ opacity: 1;
108
+ padding: 1rem 1.25rem 1.25rem;
109
+ }
110
+
111
+ .pv-search {
112
+ padding-bottom: 1rem;
113
+ }
114
+
115
+ .pv-search input {
116
+ width: 100%;
117
+ padding: 0.65rem 0.85rem;
118
+ border-radius: 0.75rem;
119
+ border: 1px solid var(--cratis-surface-border);
120
+ background: var(--cratis-surface-ground);
121
+ color: inherit;
122
+ font-size: 0.95rem;
123
+ box-shadow: inset 0 1px 0 var(--cratis-surface-border);
124
+ }
125
+
126
+ .pv-search input:focus {
127
+ outline: none;
128
+ border-color: var(--cratis-primary-color);
129
+ box-shadow: var(--cratis-focus-ring);
130
+ }
131
+
132
+ .pv-filter-group-search {
133
+ padding: 0 0 0.5rem 0;
134
+ }
135
+
136
+ .pv-filter-group-search input {
137
+ width: 100%;
138
+ padding: 0.4rem 0.6rem;
139
+ border-radius: 0.5rem;
140
+ border: 1px solid var(--cratis-surface-border);
141
+ background: var(--cratis-surface-ground);
142
+ color: inherit;
143
+ font-size: 0.85rem;
144
+ }
145
+
146
+ .pv-filter-group-search input:focus {
147
+ outline: none;
148
+ border-color: var(--cratis-primary-color);
149
+ box-shadow: var(--cratis-focus-ring);
150
+ }
151
+
152
+ /* Reusable checkbox/radio option list (CheckboxListFilter) */
153
+ .pv-option-list {
154
+ position: relative;
155
+ display: flex;
156
+ flex-direction: column;
157
+ max-height: var(--cratis-filter-option-list-max-height, 14rem);
158
+ overflow-y: auto;
159
+ }
160
+
161
+ /* Off-screen clone of every option, used only to measure whether the real (possibly
162
+ search-filtered) list would overflow the box - see useOptionListOverflow. */
163
+ .pv-option-list-mirror {
164
+ position: absolute;
165
+ inset: 0;
166
+ margin: 0;
167
+ padding: 0;
168
+ list-style: none;
169
+ visibility: hidden;
170
+ pointer-events: none;
171
+ max-height: none;
172
+ overflow: visible;
173
+ }
174
+
175
+ /* Rendered via `content: attr(...)` rather than a DOM text node - see CheckboxListFilter.tsx -
176
+ so a mirror row's label/count can never be found by a text-content query. */
177
+ .pv-option-mirror-label::before {
178
+ content: attr(data-label);
179
+ }
180
+
181
+ .pv-option-list-search {
182
+ position: sticky;
183
+ top: 0;
184
+ z-index: 1;
185
+ background: var(--cratis-surface-overlay);
186
+ }
187
+
188
+ .pv-option-list-empty {
189
+ margin: 0;
190
+ padding: 0.45rem 0.5rem;
191
+ font-size: 0.85rem;
192
+ color: var(--cratis-text-color-secondary);
193
+ }
194
+
195
+ .pv-filter-groups {
196
+ display: flex;
197
+ flex-direction: column;
198
+ gap: 0.85rem;
199
+ }
200
+
201
+ .pv-filter {
202
+ background: var(--cratis-surface-overlay);
203
+ border: 1px solid var(--cratis-surface-border);
204
+ border-radius: 0.85rem;
205
+ padding: 0.75rem 0.85rem;
206
+ transition:
207
+ border-color 180ms ease,
208
+ box-shadow 180ms ease;
209
+ }
210
+
211
+ .pv-filter.expanded {
212
+ border-color: var(--cratis-primary-color);
213
+ box-shadow: 0 15px 38px rgba(0, 0, 0, 0.3);
214
+ }
215
+
216
+ .pv-filter-trigger {
217
+ display: flex;
218
+ width: 100%;
219
+ align-items: center;
220
+ gap: 0.5rem;
221
+ }
222
+
223
+ .pv-filter-toggle {
224
+ appearance: none;
225
+ display: flex;
226
+ flex: 1;
227
+ align-items: center;
228
+ justify-content: space-between;
229
+ min-width: 0;
230
+ background: none;
231
+ border: none;
232
+ color: inherit;
233
+ padding: 0;
234
+ cursor: pointer;
235
+ font-size: 0.82rem;
236
+ font-weight: 600;
237
+ text-transform: uppercase;
238
+ letter-spacing: 0.05em;
239
+ }
240
+
241
+ .pv-filter-label {
242
+ display: flex;
243
+ align-items: center;
244
+ gap: 0.4rem;
245
+ }
246
+
247
+ .pv-filter-trigger-meta {
248
+ display: inline-flex;
249
+ align-items: center;
250
+ gap: 0.5rem;
251
+ }
252
+
253
+ .pv-filter-count {
254
+ display: inline-flex;
255
+ align-items: center;
256
+ justify-content: center;
257
+ min-width: 1.5rem;
258
+ padding: 0.15rem 0.45rem;
259
+ border-radius: 999px;
260
+ background: var(--cratis-highlight-bg);
261
+ color: var(--cratis-text-color);
262
+ font-size: 0.7rem;
263
+ }
264
+
265
+ .pv-filter-clear-header {
266
+ appearance: none;
267
+ flex: 0 0 auto;
268
+ border: none;
269
+ width: 1.5rem;
270
+ height: 1.5rem;
271
+ border-radius: 50%;
272
+ background: var(--cratis-highlight-bg);
273
+ color: var(--cratis-text-color);
274
+ font-size: 1.2rem;
275
+ line-height: 1;
276
+ display: flex;
277
+ align-items: center;
278
+ justify-content: center;
279
+ cursor: pointer;
280
+ transition:
281
+ background 160ms ease,
282
+ transform 120ms ease;
283
+ padding: 0;
284
+ }
285
+
286
+ .pv-filter-clear-header:hover {
287
+ background: var(--cratis-surface-hover);
288
+ transform: scale(1.1);
289
+ }
290
+
291
+ .pv-filter-clear-header:active {
292
+ transform: scale(0.95);
293
+ }
294
+
295
+ .pv-filter-chevron {
296
+ width: 0.65rem;
297
+ height: 0.65rem;
298
+ border-right: 2px solid var(--cratis-text-color);
299
+ border-bottom: 2px solid var(--cratis-text-color);
300
+ transform: rotate(45deg);
301
+ transition: transform 180ms ease;
302
+ }
303
+
304
+ .pv-filter.expanded .pv-filter-chevron {
305
+ transform: rotate(225deg);
306
+ }
307
+
308
+ .pv-filter-content {
309
+ overflow: hidden;
310
+ max-height: 0;
311
+ opacity: 0;
312
+ margin-top: 0;
313
+ padding-top: 0;
314
+ border-top: 1px solid transparent;
315
+ transition:
316
+ max-height 120ms ease-out,
317
+ opacity 80ms ease-out,
318
+ margin-top 120ms ease-out,
319
+ padding-top 120ms ease-out,
320
+ border-color 120ms ease-out;
321
+ }
322
+
323
+ .pv-filter-content.expanded {
324
+ max-height: 350px;
325
+ opacity: 1;
326
+ margin-top: 0.75rem;
327
+ padding-top: 0.75rem;
328
+ border-top-color: var(--cratis-surface-border);
329
+ overflow-y: auto;
330
+ }
331
+
332
+ .pv-filter-content ul {
333
+ list-style: none;
334
+ margin: 0;
335
+ padding: 0;
336
+ display: grid;
337
+ gap: 0.45rem;
338
+ }
339
+
340
+ .pv-filter-content li label {
341
+ display: grid;
342
+ grid-template-columns: auto 1fr auto;
343
+ gap: 0.6rem;
344
+ align-items: center;
345
+ padding: 0.45rem 0.5rem;
346
+ border-radius: 0.55rem;
347
+ border: 1px solid transparent;
348
+ cursor: pointer;
349
+ transition:
350
+ background 160ms ease,
351
+ border-color 160ms ease;
352
+ }
353
+
354
+ .pv-filter-content li label:hover {
355
+ background: var(--cratis-surface-hover);
356
+ }
357
+
358
+ .pv-filter-content input[type='checkbox'],
359
+ .pv-filter-content input[type='radio'] {
360
+ accent-color: var(--cratis-primary-color);
361
+ }
362
+
363
+ .pv-filter-content li label span {
364
+ font-size: 0.85rem;
365
+ }
366
+
367
+ .pv-filter-clear {
368
+ margin-top: 0.75rem;
369
+ appearance: none;
370
+ border: none;
371
+ border-radius: 0.55rem;
372
+ padding: 0.4rem 0.75rem;
373
+ background: var(--cratis-highlight-bg);
374
+ color: var(--cratis-text-color);
375
+ font-size: 0.72rem;
376
+ text-transform: uppercase;
377
+ letter-spacing: 0.08em;
378
+ cursor: pointer;
379
+ }
380
+
381
+ .pv-option-count {
382
+ font-feature-settings: 'tnum';
383
+ font-variant-numeric: tabular-nums;
384
+ color: var(--cratis-text-color-secondary);
385
+ font-size: 0.75rem;
386
+ }
387
+
388
+ /* Filter Dropdown (anchor-positioned panel) */
389
+ .pv-filter-dropdown {
390
+ position: fixed;
391
+ width: min(320px, calc(100vw - 2rem));
392
+ max-height: calc(100vh - 8rem);
393
+ background: linear-gradient(
394
+ 180deg,
395
+ var(--cratis-surface-card),
396
+ var(--cratis-surface-ground)
397
+ );
398
+ border: 1px solid var(--cratis-surface-border);
399
+ border-radius: 0.85rem;
400
+ box-shadow: var(--cratis-shadow-overlay);
401
+ backdrop-filter: blur(16px);
402
+ overflow: hidden;
403
+ z-index: var(--cratis-z-index-filter);
404
+ display: flex;
405
+ flex-direction: column;
406
+ will-change: opacity, transform;
407
+ contain: layout;
408
+ color: var(--cratis-text-color);
409
+ }
410
+
411
+ .pv-filter-dropdown-content {
412
+ padding: 1rem;
413
+ overflow-y: auto;
414
+ flex: 1;
415
+ }
416
+
417
+ /* Range Histogram Filter */
418
+ .pv-range-histogram {
419
+ padding: 0.5rem 0;
420
+ }
421
+
422
+ .pv-histogram-bars {
423
+ display: flex;
424
+ align-items: flex-end;
425
+ gap: 2px;
426
+ height: 80px;
427
+ padding: 0 2px;
428
+ margin-bottom: 0.5rem;
429
+ }
430
+
431
+ .pv-histogram-bar {
432
+ flex: 1;
433
+ min-width: 8px;
434
+ background: var(--cratis-highlight-bg);
435
+ border: none;
436
+ border-radius: 2px 2px 0 0;
437
+ cursor: pointer;
438
+ transition:
439
+ background 160ms ease,
440
+ transform 120ms ease;
441
+ padding: 0;
442
+ }
443
+
444
+ .pv-histogram-bar:hover {
445
+ background: var(--cratis-surface-hover);
446
+ transform: scaleY(1.02);
447
+ }
448
+
449
+ .pv-histogram-bar.in-range {
450
+ background: var(--cratis-primary-color);
451
+ }
452
+
453
+ .pv-histogram-bar.partial {
454
+ background: var(--cratis-highlight-bg);
455
+ }
456
+
457
+ .pv-range-slider {
458
+ position: relative;
459
+ height: 24px;
460
+ margin: 0.5rem 0;
461
+ }
462
+
463
+ .pv-range-track {
464
+ position: absolute;
465
+ top: 50%;
466
+ left: 0;
467
+ right: 0;
468
+ height: 4px;
469
+ background: var(--cratis-surface-border);
470
+ border-radius: 2px;
471
+ transform: translateY(-50%);
472
+ }
473
+
474
+ .pv-range-selection {
475
+ position: absolute;
476
+ top: 50%;
477
+ height: 4px;
478
+ background: var(--cratis-primary-color);
479
+ border-radius: 2px;
480
+ transform: translateY(-50%);
481
+ cursor: grab;
482
+ }
483
+
484
+ .pv-range-selection:active {
485
+ cursor: grabbing;
486
+ }
487
+
488
+ .pv-range-handle {
489
+ position: absolute;
490
+ top: 50%;
491
+ width: 16px;
492
+ height: 16px;
493
+ background: var(--cratis-primary-color);
494
+ border: 2px solid var(--cratis-text-color);
495
+ border-radius: 50%;
496
+ transform: translate(-50%, -50%);
497
+ cursor: ew-resize;
498
+ transition:
499
+ transform 120ms ease,
500
+ box-shadow 120ms ease;
501
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
502
+ }
503
+
504
+ .pv-range-handle:hover {
505
+ transform: translate(-50%, -50%) scale(1.15);
506
+ box-shadow: 0 4px 12px var(--cratis-primary-color);
507
+ }
508
+
509
+ .pv-range-handle:focus-visible {
510
+ outline: 2px solid var(--cratis-primary-color);
511
+ outline-offset: 3px;
512
+ }
513
+
514
+ .pv-range-labels {
515
+ display: flex;
516
+ justify-content: space-between;
517
+ font-size: 0.75rem;
518
+ color: var(--cratis-text-color-secondary);
519
+ font-variant-numeric: tabular-nums;
520
+ }
521
+
522
+ .pv-range-clear {
523
+ margin-top: 0.75rem;
524
+ appearance: none;
525
+ border: none;
526
+ border-radius: 0.55rem;
527
+ padding: 0.4rem 0.75rem;
528
+ background: var(--cratis-highlight-bg);
529
+ color: var(--cratis-text-color);
530
+ font-size: 0.72rem;
531
+ text-transform: uppercase;
532
+ letter-spacing: 0.08em;
533
+ cursor: pointer;
534
+ width: 100%;
535
+ }
536
+
537
+ .pv-range-clear:hover {
538
+ background: var(--cratis-surface-hover);
539
+ }
540
+
541
+ @media (max-width: 900px) {
542
+ .pv-filter-panel {
543
+ width: calc(100% - 2.5rem);
544
+ left: 1.25rem;
545
+ right: 1.25rem;
546
+ top: 1.25rem;
547
+ max-height: calc(100vh - 2.5rem);
548
+ }
549
+ }
550
+
551
+ @media (prefers-reduced-motion: reduce) {
552
+ :where(.pv-filter-panel, .pv-filter-dropdown),
553
+ :where(.pv-filter-panel, .pv-filter-dropdown) * {
554
+ transition: none !important;
555
+ animation: none !important;
556
+ }
557
+ }
558
+
559
+ }