@roy-ui/ui 0.0.9 → 0.0.11
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/README.md +3 -3
- package/dist/Card-6L4M4GFX.css +270 -0
- package/dist/ImageCarousel-4L4MNUP2.css +148 -0
- package/dist/{TimePicker-44EKHQEJ.css → TimePicker-LNKWKRLX.css} +128 -5
- package/dist/{TimePicker-BhRta4MK.d.ts → TimeRangePicker-CgkOBnk6.d.ts} +25 -1
- package/dist/chunk-B7QN2JTN.js +307 -0
- package/dist/chunk-B7QN2JTN.js.map +1 -0
- package/dist/{chunk-HUCK7AM7.js → chunk-PDUQROG2.js} +23 -15
- package/dist/chunk-PDUQROG2.js.map +1 -0
- package/dist/{chunk-75IGGPXL.js → chunk-QOSMU4DV.js} +321 -40
- package/dist/chunk-QOSMU4DV.js.map +1 -0
- package/dist/components/card/index.d.ts +92 -0
- package/dist/components/card/index.js +5 -0
- package/dist/components/card/index.js.map +1 -0
- package/dist/components/data-table/index.d.ts +4 -5
- package/dist/components/data-table/index.js +2 -2
- package/dist/components/time-picker/index.d.ts +19 -3
- package/dist/components/time-picker/index.js +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +5 -4
- package/package.json +5 -1
- package/dist/chunk-75IGGPXL.js.map +0 -1
- package/dist/chunk-HUCK7AM7.js.map +0 -1
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
[](https://www.npmjs.com/package/@roy-ui/ui)
|
|
10
10
|
[](https://github.com/DibbayajyotiRoy/RoyUI/blob/main/LICENSE)
|
|
11
11
|
|
|
12
|
-
**[Open the live documentation →](https://
|
|
12
|
+
**[Open the live documentation →](https://roy-ui-docs.vercel.app/components/data-table)**
|
|
13
13
|
|
|
14
14
|
<a href="https://github.com/DibbayajyotiRoy/RoyUI/blob/main/apps/docs/lib/demo/linkedin2.mp4">
|
|
15
15
|
<img
|
|
@@ -114,7 +114,7 @@ export default function OrdersTable({ orders }: { orders: Order[] }) {
|
|
|
114
114
|
|
|
115
115
|
| Component | What it does |
|
|
116
116
|
| --- | --- |
|
|
117
|
-
| **[`DataTable<T>`](https://
|
|
117
|
+
| **[`DataTable<T>`](https://roy-ui-docs.vercel.app/components/data-table)** | Generic, fully-featured **React data table**. Search across columns, sort, paginate, **drag headers to reorder**, **drag the right edge to resize**, **Columns menu** to hide & restore, **CSV / JSON export & import**, **per-zone typography** for headers / row-headers / cells, optional `fitColumns` to disable horizontal scroll, optional `localStorage` persistence. |
|
|
118
118
|
| **`Table`** + parts | Standalone primitive — `Table`, `TableHeader`, `TableBody`, `TableRow`, `TableHead`, `TableCell`. Scrollable rows (`visibleRows`, default 7), sticky header, density scale (compact / cozy / comfortable), inline `Spinner`. |
|
|
119
119
|
| **`TableSearch`** | Debounced search input, clear button, controlled & uncontrolled modes. |
|
|
120
120
|
| **`Pagination`** | Numbered pages with text Prev / Next, ellipsis, optional `Page X of Y` summary. |
|
|
@@ -325,7 +325,7 @@ Yes. `dataIO.export.enabled` adds an Export button; `dataIO.import.enabled` adds
|
|
|
325
325
|
|
|
326
326
|
## Links
|
|
327
327
|
|
|
328
|
-
- **Live documentation:** <https://
|
|
328
|
+
- **Live documentation:** <https://roy-ui-docs.vercel.app>
|
|
329
329
|
- **Source code:** <https://github.com/DibbayajyotiRoy/RoyUI>
|
|
330
330
|
- **Issues:** <https://github.com/DibbayajyotiRoy/RoyUI/issues>
|
|
331
331
|
- **Releases:** <https://github.com/DibbayajyotiRoy/RoyUI/releases>
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
.royui-card {
|
|
2
|
+
/* Surfaces and ink — every one is a variable. The default is a premium
|
|
3
|
+
off-white (not pure white), which reads warmer and reads on a white page.
|
|
4
|
+
Opt into dark with theme="dark" (.royui-card--dark) or theme="auto". */
|
|
5
|
+
--royui-card-bg: #fafaf8;
|
|
6
|
+
--royui-card-fg: #1a1a1c;
|
|
7
|
+
--royui-card-muted: rgba(0, 0, 0, 0.52);
|
|
8
|
+
--royui-card-faint: rgba(0, 0, 0, 0.42);
|
|
9
|
+
--royui-card-line: rgba(0, 0, 0, 0.08);
|
|
10
|
+
--royui-card-radius: 24px;
|
|
11
|
+
/* A thin frame around the photo. Inner radius = radius − pad keeps the
|
|
12
|
+
corners concentric (24 − 8 = 16, the gallery's own radius). */
|
|
13
|
+
--royui-card-pad: 8px;
|
|
14
|
+
--royui-card-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
|
|
15
|
+
/* The price reads as premium when it's large and light, not bold. */
|
|
16
|
+
--royui-card-price-weight: 500;
|
|
17
|
+
/* Selection stays legible on the surface — a soft tint, not the browser blue. */
|
|
18
|
+
--royui-card-selection-bg: rgba(20, 20, 22, 0.12);
|
|
19
|
+
--royui-card-selection-fg: #1a1a1c;
|
|
20
|
+
|
|
21
|
+
display: flex;
|
|
22
|
+
flex-direction: column;
|
|
23
|
+
box-sizing: border-box;
|
|
24
|
+
width: 100%;
|
|
25
|
+
max-width: 360px;
|
|
26
|
+
/* The card is its own query container, so type scales to the card's width
|
|
27
|
+
(cqi units below) rather than the viewport — it fits in a sidebar, a
|
|
28
|
+
grid cell, or full-bleed without a media query. */
|
|
29
|
+
container-type: inline-size;
|
|
30
|
+
padding: var(--royui-card-pad);
|
|
31
|
+
background: var(--royui-card-bg);
|
|
32
|
+
color: var(--royui-card-fg);
|
|
33
|
+
border-radius: var(--royui-card-radius);
|
|
34
|
+
font-family: inherit;
|
|
35
|
+
/* A ring, a contact shadow, and a soft cast — the card rests, it doesn't
|
|
36
|
+
float. The ring is firm enough to hold the edge on a white background. */
|
|
37
|
+
box-shadow:
|
|
38
|
+
0 0 0 1px rgba(0, 0, 0, 0.07),
|
|
39
|
+
0 1px 2px rgba(0, 0, 0, 0.04),
|
|
40
|
+
0 14px 34px -16px rgba(0, 0, 0, 0.22);
|
|
41
|
+
transition:
|
|
42
|
+
transform 300ms var(--royui-card-ease),
|
|
43
|
+
box-shadow 300ms var(--royui-card-ease);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.royui-card--interactive:hover {
|
|
47
|
+
transform: translateY(-2px);
|
|
48
|
+
box-shadow:
|
|
49
|
+
0 0 0 1px rgba(0, 0, 0, 0.05),
|
|
50
|
+
0 2px 4px rgba(0, 0, 0, 0.05),
|
|
51
|
+
0 22px 48px -18px rgba(0, 0, 0, 0.28);
|
|
52
|
+
}
|
|
53
|
+
/* The photo eases in a hair as the whole card lifts — barely there. */
|
|
54
|
+
.royui-card--interactive:hover .royui-carousel__img {
|
|
55
|
+
transform: scale(1.045);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/* Force a legible selection — the browser default can wash text out on the
|
|
59
|
+
off-white surface. */
|
|
60
|
+
.royui-card ::selection {
|
|
61
|
+
background: var(--royui-card-selection-bg);
|
|
62
|
+
color: var(--royui-card-selection-fg);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/* ── Badge ───────────────────────────────────────────────────────────── */
|
|
66
|
+
.royui-card__badge {
|
|
67
|
+
position: absolute;
|
|
68
|
+
top: 11px;
|
|
69
|
+
left: 11px;
|
|
70
|
+
display: inline-flex;
|
|
71
|
+
align-items: center;
|
|
72
|
+
gap: 5px;
|
|
73
|
+
padding: 4px 9px 4px 7px;
|
|
74
|
+
background: rgba(255, 255, 255, 0.9);
|
|
75
|
+
-webkit-backdrop-filter: blur(10px) saturate(1.2);
|
|
76
|
+
backdrop-filter: blur(10px) saturate(1.2);
|
|
77
|
+
border-radius: 99px;
|
|
78
|
+
color: #1a1a1c;
|
|
79
|
+
font-size: 12px;
|
|
80
|
+
font-size: clamp(11px, 3.7cqi, 12px);
|
|
81
|
+
font-weight: 400;
|
|
82
|
+
letter-spacing: 0;
|
|
83
|
+
line-height: 1;
|
|
84
|
+
box-shadow:
|
|
85
|
+
0 0 0 0.5px rgba(0, 0, 0, 0.04),
|
|
86
|
+
0 1px 2px rgba(0, 0, 0, 0.1),
|
|
87
|
+
0 3px 10px -3px rgba(0, 0, 0, 0.22);
|
|
88
|
+
}
|
|
89
|
+
.royui-card__badge-icon {
|
|
90
|
+
display: inline-flex;
|
|
91
|
+
color: #f5b400;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/* ── Body ────────────────────────────────────────────────────────────── */
|
|
95
|
+
/* Horizontal padding insets the text a touch past the photo edge; the photo
|
|
96
|
+
and button sit at the card padding so they share one clean vertical line. */
|
|
97
|
+
.royui-card__body {
|
|
98
|
+
padding: 14px 6px 2px;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.royui-card__price-row {
|
|
102
|
+
display: flex;
|
|
103
|
+
align-items: baseline;
|
|
104
|
+
flex-wrap: wrap;
|
|
105
|
+
gap: 4px 8px;
|
|
106
|
+
min-width: 0;
|
|
107
|
+
}
|
|
108
|
+
.royui-card__price {
|
|
109
|
+
font-size: 23px;
|
|
110
|
+
font-size: clamp(18px, 7.2cqi, 23px);
|
|
111
|
+
font-weight: var(--royui-card-price-weight);
|
|
112
|
+
letter-spacing: -0.03em;
|
|
113
|
+
font-variant-numeric: tabular-nums;
|
|
114
|
+
}
|
|
115
|
+
.royui-card__price-label {
|
|
116
|
+
font-size: 14px;
|
|
117
|
+
font-size: clamp(12px, 4.4cqi, 14px);
|
|
118
|
+
font-weight: 450;
|
|
119
|
+
color: var(--royui-card-muted);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.royui-card__subtitle {
|
|
123
|
+
margin: 6px 0 0;
|
|
124
|
+
font-size: 14px;
|
|
125
|
+
font-size: clamp(12.5px, 4.4cqi, 14px);
|
|
126
|
+
line-height: 1.4;
|
|
127
|
+
color: var(--royui-card-muted);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.royui-card__divider {
|
|
131
|
+
height: 1px;
|
|
132
|
+
margin: 14px 0;
|
|
133
|
+
background: var(--royui-card-line);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/* Stats stay on one row and sit flush to both content edges, so the left and
|
|
137
|
+
right margins from the card border match. The hairline divider rides the
|
|
138
|
+
middle. */
|
|
139
|
+
.royui-card__stats {
|
|
140
|
+
display: flex;
|
|
141
|
+
flex-wrap: nowrap;
|
|
142
|
+
align-items: center;
|
|
143
|
+
justify-content: space-between;
|
|
144
|
+
gap: 10px;
|
|
145
|
+
gap: clamp(8px, 3.2cqi, 10px);
|
|
146
|
+
font-size: 14px;
|
|
147
|
+
font-size: clamp(12px, 4.4cqi, 14px);
|
|
148
|
+
color: var(--royui-card-fg);
|
|
149
|
+
}
|
|
150
|
+
.royui-card__stat {
|
|
151
|
+
display: inline-flex;
|
|
152
|
+
align-items: center;
|
|
153
|
+
gap: 6px;
|
|
154
|
+
flex: none;
|
|
155
|
+
white-space: nowrap;
|
|
156
|
+
}
|
|
157
|
+
.royui-card__stat-sep {
|
|
158
|
+
flex: none;
|
|
159
|
+
width: 1px;
|
|
160
|
+
height: 15px;
|
|
161
|
+
background: var(--royui-card-line);
|
|
162
|
+
}
|
|
163
|
+
.royui-card__stat-icon {
|
|
164
|
+
display: inline-flex;
|
|
165
|
+
flex: none;
|
|
166
|
+
color: var(--royui-card-faint);
|
|
167
|
+
}
|
|
168
|
+
/* The figure carries weight; the descriptor is dimmed, like the reference. */
|
|
169
|
+
.royui-card__stat-value {
|
|
170
|
+
color: var(--royui-card-fg);
|
|
171
|
+
}
|
|
172
|
+
.royui-card__stat-label {
|
|
173
|
+
color: var(--royui-card-muted);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.royui-card__footer {
|
|
177
|
+
display: flex;
|
|
178
|
+
align-items: center;
|
|
179
|
+
justify-content: space-between;
|
|
180
|
+
flex-wrap: wrap;
|
|
181
|
+
gap: 6px 12px;
|
|
182
|
+
margin-top: 14px;
|
|
183
|
+
font-size: 14px;
|
|
184
|
+
font-size: clamp(12px, 4.4cqi, 14px);
|
|
185
|
+
}
|
|
186
|
+
.royui-card__author {
|
|
187
|
+
color: var(--royui-card-muted);
|
|
188
|
+
min-width: 0;
|
|
189
|
+
}
|
|
190
|
+
.royui-card__author-link {
|
|
191
|
+
color: var(--royui-card-fg);
|
|
192
|
+
font-weight: 550;
|
|
193
|
+
text-decoration: underline;
|
|
194
|
+
text-underline-offset: 2px;
|
|
195
|
+
text-decoration-thickness: 1px;
|
|
196
|
+
text-decoration-color: var(--royui-card-line);
|
|
197
|
+
transition: text-decoration-color 180ms var(--royui-card-ease);
|
|
198
|
+
}
|
|
199
|
+
a.royui-card__author-link:hover {
|
|
200
|
+
text-decoration-color: currentColor;
|
|
201
|
+
}
|
|
202
|
+
.royui-card__meta {
|
|
203
|
+
color: var(--royui-card-faint);
|
|
204
|
+
white-space: nowrap;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.royui-card__action {
|
|
208
|
+
margin-top: 16px;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/* ── Dark theme ──────────────────────────────────────────────────────────
|
|
212
|
+
Opt in with theme="dark" (.royui-card--dark). theme="auto" (.royui-card--auto)
|
|
213
|
+
applies the same tokens only when the OS asks for dark — so the default light
|
|
214
|
+
card is never silently swapped out from under a dark page. */
|
|
215
|
+
.royui-card--dark {
|
|
216
|
+
--royui-card-bg: #161617;
|
|
217
|
+
--royui-card-fg: #f5f5f7;
|
|
218
|
+
--royui-card-muted: rgba(255, 255, 255, 0.55);
|
|
219
|
+
--royui-card-faint: rgba(255, 255, 255, 0.4);
|
|
220
|
+
--royui-card-line: rgba(255, 255, 255, 0.1);
|
|
221
|
+
--royui-card-selection-bg: rgba(245, 245, 247, 0.2);
|
|
222
|
+
--royui-card-selection-fg: #f5f5f7;
|
|
223
|
+
box-shadow:
|
|
224
|
+
0 0 0 1px rgba(255, 255, 255, 0.1),
|
|
225
|
+
0 14px 34px -16px rgba(0, 0, 0, 0.6);
|
|
226
|
+
}
|
|
227
|
+
.royui-card--dark.royui-card--interactive:hover {
|
|
228
|
+
box-shadow:
|
|
229
|
+
0 0 0 1px rgba(255, 255, 255, 0.12),
|
|
230
|
+
0 22px 48px -18px rgba(0, 0, 0, 0.7);
|
|
231
|
+
}
|
|
232
|
+
.royui-card--dark .royui-card__badge {
|
|
233
|
+
background: rgba(28, 28, 30, 0.82);
|
|
234
|
+
color: #f5f5f7;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
@media (prefers-color-scheme: dark) {
|
|
238
|
+
.royui-card--auto {
|
|
239
|
+
--royui-card-bg: #161617;
|
|
240
|
+
--royui-card-fg: #f5f5f7;
|
|
241
|
+
--royui-card-muted: rgba(255, 255, 255, 0.55);
|
|
242
|
+
--royui-card-faint: rgba(255, 255, 255, 0.4);
|
|
243
|
+
--royui-card-line: rgba(255, 255, 255, 0.1);
|
|
244
|
+
--royui-card-selection-bg: rgba(245, 245, 247, 0.2);
|
|
245
|
+
--royui-card-selection-fg: #f5f5f7;
|
|
246
|
+
box-shadow:
|
|
247
|
+
0 0 0 1px rgba(255, 255, 255, 0.1),
|
|
248
|
+
0 14px 34px -16px rgba(0, 0, 0, 0.6);
|
|
249
|
+
}
|
|
250
|
+
.royui-card--auto.royui-card--interactive:hover {
|
|
251
|
+
box-shadow:
|
|
252
|
+
0 0 0 1px rgba(255, 255, 255, 0.12),
|
|
253
|
+
0 22px 48px -18px rgba(0, 0, 0, 0.7);
|
|
254
|
+
}
|
|
255
|
+
.royui-card--auto .royui-card__badge {
|
|
256
|
+
background: rgba(28, 28, 30, 0.82);
|
|
257
|
+
color: #f5f5f7;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
@media (prefers-reduced-motion: reduce) {
|
|
262
|
+
.royui-card,
|
|
263
|
+
.royui-card--interactive:hover {
|
|
264
|
+
transition: none;
|
|
265
|
+
transform: none;
|
|
266
|
+
}
|
|
267
|
+
.royui-card--interactive:hover .royui-carousel__img {
|
|
268
|
+
transform: none;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
.royui-carousel {
|
|
2
|
+
/* Tunables — radius and ratio are the ones you'll reach for most. */
|
|
3
|
+
--royui-carousel-ratio: 4 / 3;
|
|
4
|
+
--royui-carousel-radius: 16px;
|
|
5
|
+
--royui-carousel-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
|
|
6
|
+
--royui-carousel-dot: rgba(255, 255, 255, 0.55);
|
|
7
|
+
--royui-carousel-dot-active: #ffffff;
|
|
8
|
+
|
|
9
|
+
position: relative;
|
|
10
|
+
overflow: hidden;
|
|
11
|
+
border-radius: var(--royui-carousel-radius);
|
|
12
|
+
aspect-ratio: var(--royui-carousel-ratio);
|
|
13
|
+
background: rgba(0, 0, 0, 0.06);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.royui-carousel__viewport {
|
|
17
|
+
width: 100%;
|
|
18
|
+
height: 100%;
|
|
19
|
+
/* Let the browser own vertical scroll; we only claim the horizontal axis. */
|
|
20
|
+
touch-action: pan-y;
|
|
21
|
+
cursor: grab;
|
|
22
|
+
-webkit-tap-highlight-color: transparent;
|
|
23
|
+
}
|
|
24
|
+
.royui-carousel__viewport:active {
|
|
25
|
+
cursor: grabbing;
|
|
26
|
+
}
|
|
27
|
+
.royui-carousel__viewport:focus-visible {
|
|
28
|
+
outline: 2px solid rgba(255, 255, 255, 0.9);
|
|
29
|
+
outline-offset: -2px;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.royui-carousel__track {
|
|
33
|
+
display: flex;
|
|
34
|
+
width: 100%;
|
|
35
|
+
height: 100%;
|
|
36
|
+
/* The signature slide — long, eased, with a touch of overshoot at the tail. */
|
|
37
|
+
transition: transform 520ms var(--royui-carousel-ease);
|
|
38
|
+
will-change: transform;
|
|
39
|
+
}
|
|
40
|
+
/* While the finger is down the track tracks the pointer 1:1, no easing. */
|
|
41
|
+
.royui-carousel__track--dragging {
|
|
42
|
+
transition: none;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.royui-carousel__slide {
|
|
46
|
+
position: relative;
|
|
47
|
+
flex: 0 0 100%;
|
|
48
|
+
width: 100%;
|
|
49
|
+
height: 100%;
|
|
50
|
+
overflow: hidden;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.royui-carousel__img {
|
|
54
|
+
display: block;
|
|
55
|
+
width: 100%;
|
|
56
|
+
height: 100%;
|
|
57
|
+
object-fit: cover;
|
|
58
|
+
pointer-events: none;
|
|
59
|
+
user-select: none;
|
|
60
|
+
-webkit-user-drag: none;
|
|
61
|
+
/* Hover-zoom is driven by the card; the transition lives here. */
|
|
62
|
+
transition: transform 700ms var(--royui-carousel-ease);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/* A faint floor of shade so white dots stay legible over any photo. */
|
|
66
|
+
.royui-carousel__scrim {
|
|
67
|
+
position: absolute;
|
|
68
|
+
inset: auto 0 0 0;
|
|
69
|
+
height: 38%;
|
|
70
|
+
background: linear-gradient(to top, rgba(0, 0, 0, 0.3), transparent);
|
|
71
|
+
opacity: 0;
|
|
72
|
+
transition: opacity 320ms var(--royui-carousel-ease);
|
|
73
|
+
pointer-events: none;
|
|
74
|
+
}
|
|
75
|
+
.royui-carousel--has-dots .royui-carousel__scrim {
|
|
76
|
+
opacity: 1;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.royui-carousel__overlay {
|
|
80
|
+
position: absolute;
|
|
81
|
+
inset: 0;
|
|
82
|
+
z-index: 3;
|
|
83
|
+
pointer-events: none;
|
|
84
|
+
}
|
|
85
|
+
/* Re-enable interaction for whatever the overlay actually contains. */
|
|
86
|
+
.royui-carousel__overlay > * {
|
|
87
|
+
pointer-events: auto;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.royui-carousel__dots {
|
|
91
|
+
position: absolute;
|
|
92
|
+
inset: auto 0 12px 0;
|
|
93
|
+
z-index: 4;
|
|
94
|
+
display: flex;
|
|
95
|
+
align-items: center;
|
|
96
|
+
justify-content: center;
|
|
97
|
+
gap: 6px;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.royui-carousel__dot {
|
|
101
|
+
width: 6px;
|
|
102
|
+
height: 6px;
|
|
103
|
+
padding: 0;
|
|
104
|
+
border: none;
|
|
105
|
+
border-radius: 99px;
|
|
106
|
+
background: var(--royui-carousel-dot);
|
|
107
|
+
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.28);
|
|
108
|
+
cursor: pointer;
|
|
109
|
+
-webkit-tap-highlight-color: transparent;
|
|
110
|
+
/* The active dot doesn't pop — it stretches into a pill. */
|
|
111
|
+
transition:
|
|
112
|
+
width 380ms var(--royui-carousel-ease),
|
|
113
|
+
background 380ms var(--royui-carousel-ease),
|
|
114
|
+
opacity 380ms var(--royui-carousel-ease);
|
|
115
|
+
}
|
|
116
|
+
.royui-carousel__dot:hover {
|
|
117
|
+
background: rgba(255, 255, 255, 0.85);
|
|
118
|
+
}
|
|
119
|
+
.royui-carousel__dot--active {
|
|
120
|
+
width: 20px;
|
|
121
|
+
background: var(--royui-carousel-dot-active);
|
|
122
|
+
}
|
|
123
|
+
.royui-carousel__dot:focus-visible {
|
|
124
|
+
outline: 2px solid #fff;
|
|
125
|
+
outline-offset: 2px;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/* Screen-reader-only live region. */
|
|
129
|
+
.royui-carousel__status {
|
|
130
|
+
position: absolute;
|
|
131
|
+
width: 1px;
|
|
132
|
+
height: 1px;
|
|
133
|
+
margin: -1px;
|
|
134
|
+
padding: 0;
|
|
135
|
+
overflow: hidden;
|
|
136
|
+
clip: rect(0 0 0 0);
|
|
137
|
+
white-space: nowrap;
|
|
138
|
+
border: 0;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
@media (prefers-reduced-motion: reduce) {
|
|
142
|
+
.royui-carousel__track,
|
|
143
|
+
.royui-carousel__img,
|
|
144
|
+
.royui-carousel__dot,
|
|
145
|
+
.royui-carousel__scrim {
|
|
146
|
+
transition: none;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -15,7 +15,9 @@
|
|
|
15
15
|
--royui-tp-hand-quiet: rgba(20, 20, 20, 0.4);
|
|
16
16
|
--royui-tp-hand-active: rgb(20, 20, 20);
|
|
17
17
|
--royui-tp-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
|
|
18
|
+
--royui-tp-spring: cubic-bezier(0.34, 1.4, 0.5, 1);
|
|
18
19
|
--royui-tp-dur: 160ms;
|
|
20
|
+
--royui-tp-dur-lg: 320ms;
|
|
19
21
|
|
|
20
22
|
position: relative;
|
|
21
23
|
display: inline-block;
|
|
@@ -97,12 +99,31 @@
|
|
|
97
99
|
}
|
|
98
100
|
|
|
99
101
|
.royui-tp__variants {
|
|
102
|
+
position: relative;
|
|
100
103
|
display: inline-flex;
|
|
101
104
|
background: var(--royui-tp-hover-bg);
|
|
102
105
|
border-radius: 7px;
|
|
103
106
|
padding: 2px;
|
|
104
107
|
}
|
|
108
|
+
/* Sliding pill — tracks the active variant. */
|
|
109
|
+
.royui-tp__variant-thumb {
|
|
110
|
+
position: absolute;
|
|
111
|
+
top: 2px;
|
|
112
|
+
bottom: 2px;
|
|
113
|
+
left: 2px;
|
|
114
|
+
width: calc(50% - 2px);
|
|
115
|
+
background: var(--royui-tp-bg);
|
|
116
|
+
border-radius: 5px;
|
|
117
|
+
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
|
|
118
|
+
transition: transform var(--royui-tp-dur-lg) var(--royui-tp-spring);
|
|
119
|
+
pointer-events: none;
|
|
120
|
+
}
|
|
121
|
+
.royui-tp__variants[data-active='digital'] .royui-tp__variant-thumb {
|
|
122
|
+
transform: translateX(100%);
|
|
123
|
+
}
|
|
105
124
|
.royui-tp__variant {
|
|
125
|
+
position: relative;
|
|
126
|
+
z-index: 1;
|
|
106
127
|
background: transparent;
|
|
107
128
|
border: 0;
|
|
108
129
|
padding: 4px 10px;
|
|
@@ -111,17 +132,13 @@
|
|
|
111
132
|
color: var(--royui-tp-muted);
|
|
112
133
|
cursor: pointer;
|
|
113
134
|
border-radius: 5px;
|
|
114
|
-
transition:
|
|
115
|
-
background var(--royui-tp-dur) var(--royui-tp-ease),
|
|
116
|
-
color var(--royui-tp-dur) var(--royui-tp-ease);
|
|
135
|
+
transition: color var(--royui-tp-dur) var(--royui-tp-ease);
|
|
117
136
|
}
|
|
118
137
|
.royui-tp__variant:hover {
|
|
119
138
|
color: var(--royui-tp-fg);
|
|
120
139
|
}
|
|
121
140
|
.royui-tp__variant--on {
|
|
122
|
-
background: var(--royui-tp-bg);
|
|
123
141
|
color: var(--royui-tp-fg);
|
|
124
|
-
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
|
|
125
142
|
}
|
|
126
143
|
|
|
127
144
|
.royui-tp__body {
|
|
@@ -130,6 +147,38 @@
|
|
|
130
147
|
padding: 4px 0 8px;
|
|
131
148
|
}
|
|
132
149
|
|
|
150
|
+
/* ── Analog ↔ Digital crossfade ─────────────────────────── */
|
|
151
|
+
|
|
152
|
+
.royui-tp__switch {
|
|
153
|
+
position: relative;
|
|
154
|
+
width: 100%;
|
|
155
|
+
transition: height var(--royui-tp-dur-lg) var(--royui-tp-ease);
|
|
156
|
+
overflow: hidden;
|
|
157
|
+
}
|
|
158
|
+
.royui-tp__layer {
|
|
159
|
+
position: absolute;
|
|
160
|
+
top: 0;
|
|
161
|
+
left: 0;
|
|
162
|
+
right: 0;
|
|
163
|
+
display: flex;
|
|
164
|
+
justify-content: center;
|
|
165
|
+
opacity: 0;
|
|
166
|
+
transform: scale(0.96);
|
|
167
|
+
filter: blur(4px);
|
|
168
|
+
pointer-events: none;
|
|
169
|
+
transition:
|
|
170
|
+
opacity var(--royui-tp-dur-lg) var(--royui-tp-ease),
|
|
171
|
+
transform var(--royui-tp-dur-lg) var(--royui-tp-ease),
|
|
172
|
+
filter var(--royui-tp-dur-lg) var(--royui-tp-ease);
|
|
173
|
+
}
|
|
174
|
+
.royui-tp__layer--active {
|
|
175
|
+
position: relative;
|
|
176
|
+
opacity: 1;
|
|
177
|
+
transform: none;
|
|
178
|
+
filter: none;
|
|
179
|
+
pointer-events: auto;
|
|
180
|
+
}
|
|
181
|
+
|
|
133
182
|
/* ── Analog ─────────────────────────────────────────────── */
|
|
134
183
|
|
|
135
184
|
.royui-tp-analog {
|
|
@@ -373,6 +422,74 @@
|
|
|
373
422
|
border: 1px solid var(--royui-tp-accent);
|
|
374
423
|
}
|
|
375
424
|
|
|
425
|
+
/* ── Range — Start / End legs ───────────────────────────── */
|
|
426
|
+
|
|
427
|
+
.royui-trp__legs {
|
|
428
|
+
position: relative;
|
|
429
|
+
display: grid;
|
|
430
|
+
grid-template-columns: 1fr 1fr;
|
|
431
|
+
gap: 2px;
|
|
432
|
+
background: var(--royui-tp-hover-bg);
|
|
433
|
+
border-radius: 9px;
|
|
434
|
+
padding: 3px;
|
|
435
|
+
margin-bottom: 12px;
|
|
436
|
+
}
|
|
437
|
+
.royui-trp__leg-thumb {
|
|
438
|
+
position: absolute;
|
|
439
|
+
top: 3px;
|
|
440
|
+
bottom: 3px;
|
|
441
|
+
left: 3px;
|
|
442
|
+
width: calc(50% - 3px);
|
|
443
|
+
background: var(--royui-tp-bg);
|
|
444
|
+
border: 1px solid var(--royui-tp-border);
|
|
445
|
+
border-radius: 7px;
|
|
446
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.07);
|
|
447
|
+
transition: transform var(--royui-tp-dur-lg) var(--royui-tp-spring);
|
|
448
|
+
pointer-events: none;
|
|
449
|
+
}
|
|
450
|
+
.royui-trp__legs[data-active='to'] .royui-trp__leg-thumb {
|
|
451
|
+
transform: translateX(100%);
|
|
452
|
+
}
|
|
453
|
+
.royui-trp__leg {
|
|
454
|
+
position: relative;
|
|
455
|
+
z-index: 1;
|
|
456
|
+
display: flex;
|
|
457
|
+
flex-direction: column;
|
|
458
|
+
align-items: flex-start;
|
|
459
|
+
gap: 1px;
|
|
460
|
+
background: transparent;
|
|
461
|
+
border: 0;
|
|
462
|
+
padding: 6px 11px;
|
|
463
|
+
border-radius: 7px;
|
|
464
|
+
cursor: pointer;
|
|
465
|
+
font: inherit;
|
|
466
|
+
}
|
|
467
|
+
.royui-trp__leg-label {
|
|
468
|
+
font-size: 10.5px;
|
|
469
|
+
font-weight: 500;
|
|
470
|
+
letter-spacing: 0.03em;
|
|
471
|
+
text-transform: uppercase;
|
|
472
|
+
color: var(--royui-tp-subtle);
|
|
473
|
+
transition: color var(--royui-tp-dur) var(--royui-tp-ease);
|
|
474
|
+
}
|
|
475
|
+
.royui-trp__leg-time {
|
|
476
|
+
font-size: 15px;
|
|
477
|
+
font-weight: 500;
|
|
478
|
+
color: var(--royui-tp-muted);
|
|
479
|
+
font-variant-numeric: tabular-nums;
|
|
480
|
+
letter-spacing: -0.01em;
|
|
481
|
+
transition: color var(--royui-tp-dur) var(--royui-tp-ease);
|
|
482
|
+
}
|
|
483
|
+
.royui-trp__leg[aria-selected='true'] .royui-trp__leg-label {
|
|
484
|
+
color: var(--royui-tp-muted);
|
|
485
|
+
}
|
|
486
|
+
.royui-trp__leg[aria-selected='true'] .royui-trp__leg-time {
|
|
487
|
+
color: var(--royui-tp-fg);
|
|
488
|
+
}
|
|
489
|
+
.royui-trp__leg:hover .royui-trp__leg-time {
|
|
490
|
+
color: var(--royui-tp-fg);
|
|
491
|
+
}
|
|
492
|
+
|
|
376
493
|
@keyframes royui-tp-in {
|
|
377
494
|
from { opacity: 0; transform: translateY(-4px) scale(0.98); }
|
|
378
495
|
to { opacity: 1; transform: none; }
|
|
@@ -408,4 +525,10 @@
|
|
|
408
525
|
|
|
409
526
|
@media (prefers-reduced-motion: reduce) {
|
|
410
527
|
.royui-tp__panel { animation: none; }
|
|
528
|
+
.royui-tp__switch,
|
|
529
|
+
.royui-tp__layer,
|
|
530
|
+
.royui-tp__variant-thumb,
|
|
531
|
+
.royui-trp__leg-thumb {
|
|
532
|
+
transition: none;
|
|
533
|
+
}
|
|
411
534
|
}
|
|
@@ -36,4 +36,28 @@ interface TimePickerProps {
|
|
|
36
36
|
declare function formatTime(t: TimeValue | null | undefined, hourCycle?: 12 | 24): string;
|
|
37
37
|
declare function TimePicker({ value, defaultValue, onChange, variant, switchable, hourCycle, minuteStep, placeholder, align, className, style, triggerLabel, disabled, }: TimePickerProps): react_jsx_runtime.JSX.Element;
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
type TimeRangeValue = {
|
|
40
|
+
from: TimeValue | null;
|
|
41
|
+
to: TimeValue | null;
|
|
42
|
+
};
|
|
43
|
+
interface TimeRangePickerProps {
|
|
44
|
+
value?: TimeRangeValue | null;
|
|
45
|
+
defaultValue?: TimeRangeValue | null;
|
|
46
|
+
onChange?: (next: TimeRangeValue) => void;
|
|
47
|
+
/** Picker style. Default 'analog'. */
|
|
48
|
+
variant?: TimePickerVariant;
|
|
49
|
+
/** Allow the user to switch between variants. Default true. */
|
|
50
|
+
switchable?: boolean;
|
|
51
|
+
hourCycle?: 12 | 24;
|
|
52
|
+
minuteStep?: number;
|
|
53
|
+
placeholder?: string;
|
|
54
|
+
align?: 'left' | 'right';
|
|
55
|
+
className?: string;
|
|
56
|
+
style?: CSSProperties;
|
|
57
|
+
triggerLabel?: ReactNode;
|
|
58
|
+
disabled?: boolean;
|
|
59
|
+
}
|
|
60
|
+
declare function formatTimeRange(range: TimeRangeValue | null | undefined, hourCycle?: 12 | 24): string;
|
|
61
|
+
declare function TimeRangePicker({ value, defaultValue, onChange, variant, switchable, hourCycle, minuteStep, placeholder, align, className, style, triggerLabel, disabled, }: TimeRangePickerProps): react_jsx_runtime.JSX.Element;
|
|
62
|
+
|
|
63
|
+
export { AnalogClock as A, TimePicker as T, type AnalogClockProps as a, type TimePickerProps as b, type TimePickerVariant as c, TimeRangePicker as d, type TimeRangePickerProps as e, type TimeRangeValue as f, type TimeValue as g, formatTime as h, formatTimeRange as i };
|