@esportsplus/ui 0.56.2 → 0.56.4

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,474 @@
1
+ import * as template_u1 from '@esportsplus/template';
2
+ import { component } from '@esportsplus/template';
3
+ import './scss/index.scss';
4
+ const template_1a5zh7n1 = template_u1.template(`<div class='surface-field-surface'><button class='surface-field-surface-handle' type='button'></button><div class='surface-field-surface-content'></div><button class='surface-field-surface-resize' type='button'>`);
5
+ const template_1a5zh7n7 = template_u1.template(`<div class='surface-field'><canvas aria-hidden='true' class='surface-field-canvas'></canvas><div class='surface-field-content'>`);
6
+ const ALPHA_LEVELS = 32;
7
+ const DEFAULTS = {
8
+ accent: '#6683e8',
9
+ base: 0.14,
10
+ breathe: 0,
11
+ brightness: 0.2,
12
+ camera: null,
13
+ connected: true,
14
+ gap: 22,
15
+ lineRadius: 200,
16
+ pointerPush: 2,
17
+ radius: 250,
18
+ ripplePush: 6,
19
+ still: false,
20
+ surfacePadding: 0,
21
+ tint: 0,
22
+ wander: false
23
+ };
24
+ const IDLE = 1500;
25
+ const KEYS = Object.keys(DEFAULTS);
26
+ const HALO = 0.75;
27
+ const RIPPLE_LIFE = 1.4;
28
+ const RIPPLE_SPEED = 520;
29
+ const RIPPLE_WIDTH = 36;
30
+ const SELECTOR = '.surface-field-surface, [data-surface-field]';
31
+ const TAU = Math.PI * 2;
32
+ const TINT_LEVELS = 5;
33
+ let colors = new Map(), probe = null, z = 1;
34
+ function clamp(value, min, max) {
35
+ return Math.min(max, Math.max(min, value));
36
+ }
37
+ function falloff(distance, radius) {
38
+ if (radius <= 0 || distance >= radius) {
39
+ return 0;
40
+ }
41
+ let t = distance / radius;
42
+ return (1 - t * t) * (1 - t * t);
43
+ }
44
+ function rgb(color) {
45
+ let cached = colors.get(color);
46
+ if (cached) {
47
+ return cached;
48
+ }
49
+ probe ??= document.createElement('canvas').getContext('2d', { willReadFrequently: true });
50
+ probe.clearRect(0, 0, 1, 1);
51
+ probe.fillStyle = '#000';
52
+ probe.fillStyle = color;
53
+ probe.fillRect(0, 0, 1, 1);
54
+ let data = probe.getImageData(0, 0, 1, 1).data, value = [data[0], data[1], data[2]];
55
+ if (colors.size > 64) {
56
+ colors.clear();
57
+ }
58
+ colors.set(color, value);
59
+ return value;
60
+ }
61
+ const surface = component(function ({ bounded = true, height = 160, label = 'surface', minHeight = 72, minWidth = 120, state, width = 240, x = 0, y = 0, ...attributes }, content) {
62
+ let element, start = null;
63
+ if (state) {
64
+ ({ height, width, x, y } = state);
65
+ }
66
+ function apply() {
67
+ if (!element) {
68
+ return;
69
+ }
70
+ let parent = element.parentElement;
71
+ width = Math.max(minWidth, width);
72
+ height = Math.max(minHeight, height);
73
+ if (bounded && parent) {
74
+ let pw = parent.clientWidth, ph = parent.clientHeight;
75
+ width = clamp(width, minWidth, Math.max(minWidth, pw));
76
+ height = clamp(height, minHeight, Math.max(minHeight, ph));
77
+ x = clamp(x, 0, Math.max(0, pw - width));
78
+ y = clamp(y, 0, Math.max(0, ph - height));
79
+ }
80
+ element.style.height = `${height}px`;
81
+ element.style.translate = `${x}px ${y}px`;
82
+ element.style.width = `${width}px`;
83
+ if (state && (state.height !== height || state.width !== width || state.x !== x || state.y !== y)) {
84
+ state.height = height;
85
+ state.width = width;
86
+ state.x = x;
87
+ state.y = y;
88
+ }
89
+ }
90
+ function begin(event) {
91
+ if (event.button !== 0 || !element) {
92
+ return;
93
+ }
94
+ event.currentTarget.setPointerCapture(event.pointerId);
95
+ element.classList.add('--active');
96
+ element.style.zIndex = String(++z);
97
+ start = {
98
+ h: height,
99
+ pointerX: event.clientX,
100
+ pointerY: event.clientY,
101
+ scale: element.getBoundingClientRect().width / element.offsetWidth || 1,
102
+ w: width,
103
+ x,
104
+ y
105
+ };
106
+ }
107
+ function end() {
108
+ element?.classList.remove('--active');
109
+ start = null;
110
+ }
111
+ function nudge(event, resize) {
112
+ let step = event.shiftKey ? 32 : 8, dx = event.key === 'ArrowLeft' ? -step : event.key === 'ArrowRight' ? step : 0, dy = event.key === 'ArrowUp' ? -step : event.key === 'ArrowDown' ? step : 0;
113
+ if (!dx && !dy) {
114
+ return;
115
+ }
116
+ event.preventDefault();
117
+ if (resize) {
118
+ width += dx;
119
+ height += dy;
120
+ }
121
+ else {
122
+ x += dx;
123
+ y += dy;
124
+ }
125
+ apply();
126
+ }
127
+ return (() => {
128
+ let root_1a5zh7n0 = template_1a5zh7n1(), element_1a5zh7n2 = root_1a5zh7n0.firstChild, element_1a5zh7n3 = element_1a5zh7n2.firstElementChild, element_1a5zh7n4 = element_1a5zh7n3.nextElementSibling, element_1a5zh7n5 = element_1a5zh7n4.nextElementSibling;
129
+ template_u1.setProperties(element_1a5zh7n2, this?.attributes);
130
+ template_u1.setProperties(element_1a5zh7n2, attributes);
131
+ template_u1.onconnect(element_1a5zh7n2, (el) => {
132
+ element = el;
133
+ apply();
134
+ });
135
+ template_u1.setProperty(element_1a5zh7n3, 'aria-label', `Move ${label} surface with arrow keys`);
136
+ template_u1.delegate(element_1a5zh7n3, 'keydown', (event) => nudge(event, false));
137
+ template_u1.delegate(element_1a5zh7n3, 'lostpointercapture', end);
138
+ template_u1.delegate(element_1a5zh7n3, 'pointerdown', begin);
139
+ template_u1.delegate(element_1a5zh7n3, 'pointermove', (event) => {
140
+ if (!start) {
141
+ return;
142
+ }
143
+ x = start.x + (event.clientX - start.pointerX) / start.scale;
144
+ y = start.y + (event.clientY - start.pointerY) / start.scale;
145
+ apply();
146
+ });
147
+ template_u1.slot(element_1a5zh7n4, content, 1);
148
+ template_u1.setProperty(element_1a5zh7n5, 'aria-label', `Resize ${label} surface with arrow keys; right and down make it larger`);
149
+ template_u1.delegate(element_1a5zh7n5, 'keydown', (event) => nudge(event, true));
150
+ template_u1.delegate(element_1a5zh7n5, 'lostpointercapture', end);
151
+ template_u1.delegate(element_1a5zh7n5, 'pointerdown', begin);
152
+ template_u1.delegate(element_1a5zh7n5, 'pointermove', (event) => {
153
+ if (!start) {
154
+ return;
155
+ }
156
+ width = start.w + (event.clientX - start.pointerX) / start.scale;
157
+ height = start.h + (event.clientY - start.pointerY) / start.scale;
158
+ apply();
159
+ });
160
+ return root_1a5zh7n0;
161
+ })();
162
+ });
163
+ export default Object.assign(component(function (attributes, content) {
164
+ let given = {}, rest = {}, state = attributes.state;
165
+ for (let key in attributes) {
166
+ if (key === 'state') {
167
+ continue;
168
+ }
169
+ if (KEYS.includes(key)) {
170
+ given[key] = attributes[key];
171
+ }
172
+ else {
173
+ rest[key] = attributes[key];
174
+ }
175
+ }
176
+ let canvas, context = null, frame = 0, host, key = '', last = 0, light = { intensity: 0, x: 0, y: 0 }, reduced = matchMedia('(prefers-reduced-motion: reduce)'), observer, pointer = { at: -Infinity, inside: false, x: 0, y: 0 }, ripples = [], size = { dpr: 0, height: 0, width: 0 }, visible = false;
177
+ let bucket = new Uint16Array(0), dotAlpha = new Float32Array(0), dotLight = new Float32Array(0), lineLight = new Float32Array(0), order = new Uint32Array(0), px = new Float32Array(0), py = new Float32Array(0), segment = new Uint32Array(0), segmentBucket = new Uint16Array(0), segmentOrder = new Uint32Array(0), seed = new Float32Array(0);
178
+ function options() {
179
+ let snapshot = {};
180
+ for (let i = 0, n = KEYS.length; i < n; i++) {
181
+ let k = KEYS[i];
182
+ snapshot[k] = state?.[k] ?? given[k] ?? DEFAULTS[k];
183
+ }
184
+ let camera = snapshot.camera;
185
+ if (camera) {
186
+ snapshot.camera = { x: camera.x, y: camera.y, zoom: camera.zoom };
187
+ }
188
+ return snapshot;
189
+ }
190
+ function grow(n) {
191
+ if (px.length >= n) {
192
+ return;
193
+ }
194
+ bucket = new Uint16Array(n);
195
+ dotAlpha = new Float32Array(n);
196
+ dotLight = new Float32Array(n);
197
+ lineLight = new Float32Array(n);
198
+ order = new Uint32Array(n);
199
+ px = new Float32Array(n);
200
+ py = new Float32Array(n);
201
+ segment = new Uint32Array(n * 4);
202
+ segmentBucket = new Uint16Array(n * 2);
203
+ segmentOrder = new Uint32Array(n * 2);
204
+ seed = new Float32Array(n);
205
+ }
206
+ function start() {
207
+ if (!frame && visible && host?.isConnected) {
208
+ last = performance.now();
209
+ frame = requestAnimationFrame(tick);
210
+ }
211
+ }
212
+ function stop() {
213
+ cancelAnimationFrame(frame);
214
+ frame = 0;
215
+ }
216
+ function tick(now) {
217
+ frame = requestAnimationFrame(tick);
218
+ if (!host || !canvas || !context) {
219
+ return;
220
+ }
221
+ let dt = Math.min(64, now - last) / 1000, o = options(), width = host.clientWidth, height = host.clientHeight, dpr = Math.min(2, devicePixelRatio || 1);
222
+ last = now;
223
+ if (width !== size.width || height !== size.height || dpr !== size.dpr) {
224
+ canvas.height = Math.max(1, Math.round(height * dpr));
225
+ canvas.width = Math.max(1, Math.round(width * dpr));
226
+ size = { dpr, height, width };
227
+ key = '';
228
+ }
229
+ let bounds = host.getBoundingClientRect(), elements = host.querySelectorAll(SELECTOR), rects = [];
230
+ for (let i = 0, n = elements.length; i < n; i++) {
231
+ let r = elements[i].getBoundingClientRect();
232
+ if (r.width && r.height) {
233
+ rects.push({
234
+ bottom: r.bottom - bounds.top,
235
+ left: r.left - bounds.left,
236
+ right: r.right - bounds.left,
237
+ top: r.top - bounds.top
238
+ });
239
+ }
240
+ }
241
+ let animate = !o.still && !reduced.matches, intensity = 0, target = { x: light.x, y: light.y }, wandering = false;
242
+ if (animate && pointer.inside) {
243
+ intensity = 1;
244
+ target = { x: pointer.x, y: pointer.y };
245
+ }
246
+ else if (animate && o.wander && now - pointer.at > IDLE) {
247
+ let t = now / 1000;
248
+ intensity = 0.85;
249
+ target = {
250
+ x: width / 2 + Math.cos(t * 0.23) * width * 0.34 + Math.sin(t * 0.57) * width * 0.08,
251
+ y: height / 2 + Math.sin(t * 0.31) * height * 0.3 + Math.cos(t * 0.49) * height * 0.08
252
+ };
253
+ wandering = true;
254
+ }
255
+ if (light.intensity < 0.01 && intensity > 0) {
256
+ light.x = target.x;
257
+ light.y = target.y;
258
+ }
259
+ let follow = 1 - Math.exp(-dt * (wandering ? 2.5 : 16)), fade = 1 - Math.exp(-dt * 6);
260
+ light.intensity += (intensity - light.intensity) * fade;
261
+ light.x += (target.x - light.x) * follow;
262
+ light.y += (target.y - light.y) * follow;
263
+ if (!animate) {
264
+ light.intensity = 0;
265
+ ripples.length = 0;
266
+ }
267
+ else if (ripples.length) {
268
+ ripples = ripples.filter((ripple) => (now - ripple.born) / 1000 < RIPPLE_LIFE);
269
+ }
270
+ let color = getComputedStyle(canvas).color, settled = Math.abs(intensity - light.intensity) < 0.002
271
+ && (light.intensity < 0.002 || (Math.abs(target.x - light.x) < 0.1 && Math.abs(target.y - light.y) < 0.1)), signature = JSON.stringify([o, color, rects, pointer.inside && animate ? [pointer.x, pointer.y] : 0]);
272
+ if (settled && !wandering && !ripples.length && !(animate && o.breathe > 0) && signature === key) {
273
+ return;
274
+ }
275
+ key = signature;
276
+ draw(o, rects, color, animate ? now : 0, animate);
277
+ }
278
+ function draw(o, rects, color, now, animate) {
279
+ let ctx = context, { dpr, height, width } = size, camera = o.camera, gap = Math.max(6, o.gap) * (camera ? Math.max(0.01, camera.zoom) : 1), zoom = camera ? Math.max(0.01, camera.zoom) : 1;
280
+ while (gap < 8) {
281
+ gap *= 2;
282
+ }
283
+ let cols = Math.floor(width / gap) + 2, rows = Math.floor(height / gap) + 2, n = cols * rows, i0 = camera ? Math.floor(-camera.x / gap) : 0, j0 = camera ? Math.floor(-camera.y / gap) : 0, ox = camera ? camera.x + i0 * gap : (width - (cols - 1) * gap) / 2, oy = camera ? camera.y + j0 * gap : (height - (rows - 1) * gap) / 2, padding = o.surfacePadding * zoom, clear = Math.max(2, gap * 0.8 + padding), band = Math.max(clear + gap, gap * 3 + padding), halo = band + gap * 1.5, push = Math.min(o.radius, gap * 5), peak = Math.min(1, o.brightness * 2.5), time = now / 1000;
284
+ grow(n);
285
+ for (let j = 0; j < rows; j++) {
286
+ for (let i = 0; i < cols; i++) {
287
+ let k = j * cols + i, x = ox + i * gap, y = oy + j * gap, glow = 0, shown = 1;
288
+ seed[k] = ((Math.sin((i + i0) * 12.9898 + (j + j0) * 78.233) * 43758.5453) % 1 + 1) % 1;
289
+ for (let r = 0, m = rects.length; r < m; r++) {
290
+ let rect = rects[r], cx = clamp(x, rect.left, rect.right), cy = clamp(y, rect.top, rect.bottom), dx = x - cx, dy = y - cy, d = Math.sqrt(dx * dx + dy * dy);
291
+ if (d === 0) {
292
+ shown = 0;
293
+ break;
294
+ }
295
+ if (d < halo) {
296
+ glow = Math.max(glow, 1 - d / halo);
297
+ }
298
+ if (d < band) {
299
+ let scale = (clear + d * (band - clear) / band) / d;
300
+ x = cx + dx * scale;
301
+ y = cy + dy * scale;
302
+ }
303
+ }
304
+ let dot = glow * glow * HALO, line = dot;
305
+ if (shown && light.intensity > 0.001) {
306
+ let dx = x - light.x, dy = y - light.y, d = Math.sqrt(dx * dx + dy * dy);
307
+ dot += falloff(d, o.radius) * light.intensity;
308
+ line += falloff(d, o.lineRadius) * light.intensity;
309
+ if (pointer.inside && o.pointerPush && d > 0.001 && d < push) {
310
+ let s = o.pointerPush * (1 - d / push) * (1 - d / push) * light.intensity / d;
311
+ x += dx * s;
312
+ y += dy * s;
313
+ }
314
+ }
315
+ for (let r = 0, m = shown ? ripples.length : 0; r < m; r++) {
316
+ let ripple = ripples[r], age = (now - ripple.born) / 1000, dx = x - ripple.x, dy = y - ripple.y, d = Math.sqrt(dx * dx + dy * dy), life = 1 - age / RIPPLE_LIFE, wave = (d - age * RIPPLE_SPEED) / RIPPLE_WIDTH, strength = Math.exp(-wave * wave) * life * life;
317
+ if (d > 0.001) {
318
+ x += dx / d * o.ripplePush * strength;
319
+ y += dy / d * o.ripplePush * strength;
320
+ }
321
+ dot += strength * 0.8;
322
+ line += strength * 0.6;
323
+ }
324
+ let breath = animate && o.breathe > 0
325
+ ? 1 - o.breathe * 0.5 * (1 + Math.sin(time * 1.3 + seed[k] * TAU))
326
+ : 1;
327
+ dot = Math.min(1, dot);
328
+ px[k] = x;
329
+ py[k] = y;
330
+ dotLight[k] = dot;
331
+ dotAlpha[k] = shown * breath * (o.base + (peak - o.base) * Math.max(0, dot));
332
+ lineLight[k] = shown * Math.min(1, line);
333
+ }
334
+ }
335
+ let accent = rgb(o.accent), base = rgb(color), buckets = ALPHA_LEVELS * TINT_LEVELS, counts = new Uint32Array(buckets + 1), fills = [], tint = clamp(o.tint, 0, 1);
336
+ for (let t = 0; t < TINT_LEVELS; t++) {
337
+ let mix = tint * t / (TINT_LEVELS - 1);
338
+ fills[t] = `rgb(${Math.round(base[0] + (accent[0] - base[0]) * mix)} ${Math.round(base[1] + (accent[1] - base[1]) * mix)} ${Math.round(base[2] + (accent[2] - base[2]) * mix)})`;
339
+ }
340
+ ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
341
+ ctx.clearRect(0, 0, width, height);
342
+ if (o.connected) {
343
+ let segments = 0;
344
+ for (let j = 0; j < rows; j++) {
345
+ for (let i = 0; i < cols; i++) {
346
+ let k = j * cols + i;
347
+ for (let neighbour of [i + 1 < cols ? k + 1 : -1, j + 1 < rows ? k + cols : -1]) {
348
+ if (neighbour < 0) {
349
+ continue;
350
+ }
351
+ let lit = Math.min(lineLight[k], lineLight[neighbour]), alpha = Math.round(lit * o.brightness * (ALPHA_LEVELS - 1));
352
+ if (alpha < 1) {
353
+ continue;
354
+ }
355
+ segment[segments * 2] = k;
356
+ segment[segments * 2 + 1] = neighbour;
357
+ segmentBucket[segments] = Math.round(lit * (TINT_LEVELS - 1)) * ALPHA_LEVELS + Math.min(alpha, ALPHA_LEVELS - 1);
358
+ counts[segmentBucket[segments] + 1]++;
359
+ segments++;
360
+ }
361
+ }
362
+ }
363
+ sort(counts, segmentBucket, segmentOrder, segments);
364
+ ctx.lineWidth = 1;
365
+ for (let b = 0; b < buckets; b++) {
366
+ let from = counts[b], to = counts[b + 1];
367
+ if (from === to) {
368
+ continue;
369
+ }
370
+ ctx.beginPath();
371
+ for (let s = from; s < to; s++) {
372
+ let a = segment[segmentOrder[s] * 2], c = segment[segmentOrder[s] * 2 + 1];
373
+ ctx.moveTo(px[a], py[a]);
374
+ ctx.lineTo(px[c], py[c]);
375
+ }
376
+ ctx.globalAlpha = (b % ALPHA_LEVELS) / (ALPHA_LEVELS - 1);
377
+ ctx.strokeStyle = fills[Math.floor(b / ALPHA_LEVELS)];
378
+ ctx.stroke();
379
+ }
380
+ counts.fill(0);
381
+ }
382
+ let dots = 0;
383
+ for (let k = 0; k < n; k++) {
384
+ let alpha = Math.round(dotAlpha[k] * (ALPHA_LEVELS - 1));
385
+ if (alpha < 1) {
386
+ bucket[k] = buckets;
387
+ continue;
388
+ }
389
+ bucket[k] = Math.round(dotLight[k] * (TINT_LEVELS - 1)) * ALPHA_LEVELS + Math.min(alpha, ALPHA_LEVELS - 1);
390
+ counts[bucket[k] + 1]++;
391
+ dots++;
392
+ }
393
+ sort(counts, bucket, order, n);
394
+ for (let b = 0; b < buckets; b++) {
395
+ let from = counts[b], to = counts[b + 1];
396
+ if (from === to) {
397
+ continue;
398
+ }
399
+ let r = 0.85 + 0.45 * Math.floor(b / ALPHA_LEVELS) / (TINT_LEVELS - 1);
400
+ ctx.beginPath();
401
+ for (let s = from; s < to; s++) {
402
+ let k = order[s];
403
+ ctx.moveTo(px[k] + r, py[k]);
404
+ ctx.arc(px[k], py[k], r, 0, TAU);
405
+ }
406
+ ctx.globalAlpha = (b % ALPHA_LEVELS) / (ALPHA_LEVELS - 1);
407
+ ctx.fillStyle = fills[Math.floor(b / ALPHA_LEVELS)];
408
+ ctx.fill();
409
+ }
410
+ ctx.globalAlpha = 1;
411
+ }
412
+ function sort(counts, keys, into, n) {
413
+ for (let b = 1, m = counts.length; b < m; b++) {
414
+ counts[b] += counts[b - 1];
415
+ }
416
+ let cursor = counts.slice();
417
+ for (let i = 0; i < n; i++) {
418
+ if (keys[i] < counts.length - 1) {
419
+ into[cursor[keys[i]]++] = i;
420
+ }
421
+ }
422
+ }
423
+ function track(event) {
424
+ if (!host) {
425
+ return;
426
+ }
427
+ let bounds = host.getBoundingClientRect();
428
+ pointer.at = performance.now();
429
+ pointer.inside = true;
430
+ pointer.x = event.clientX - bounds.left;
431
+ pointer.y = event.clientY - bounds.top;
432
+ }
433
+ return (() => {
434
+ let root_1a5zh7n6 = template_1a5zh7n7(), element_1a5zh7n8 = root_1a5zh7n6.firstChild, element_1a5zh7n9 = element_1a5zh7n8.firstElementChild.nextElementSibling;
435
+ template_u1.setProperties(element_1a5zh7n8, this?.attributes);
436
+ template_u1.setProperties(element_1a5zh7n8, rest);
437
+ template_u1.onconnect(element_1a5zh7n8, (element) => {
438
+ host = element;
439
+ canvas = element.querySelector('.surface-field-canvas');
440
+ context = canvas.getContext('2d');
441
+ observer = new IntersectionObserver((entries) => {
442
+ visible = entries[entries.length - 1].isIntersecting;
443
+ if (visible) {
444
+ start();
445
+ }
446
+ else {
447
+ stop();
448
+ }
449
+ });
450
+ observer.observe(element);
451
+ });
452
+ template_u1.ondisconnect(element_1a5zh7n8, () => {
453
+ observer?.disconnect();
454
+ stop();
455
+ });
456
+ template_u1.delegate(element_1a5zh7n8, 'pointerdown', (event) => {
457
+ track(event);
458
+ if (event.button !== 0 || event.target.closest?.(SELECTOR)) {
459
+ return;
460
+ }
461
+ ripples.push({ born: performance.now(), x: pointer.x, y: pointer.y });
462
+ if (ripples.length > 6) {
463
+ ripples.shift();
464
+ }
465
+ });
466
+ template_u1.on(element_1a5zh7n8, 'pointerleave', () => {
467
+ pointer.at = performance.now();
468
+ pointer.inside = false;
469
+ });
470
+ template_u1.delegate(element_1a5zh7n8, 'pointermove', track);
471
+ template_u1.slot(element_1a5zh7n9, content, 1);
472
+ return root_1a5zh7n6;
473
+ })();
474
+ }), { surface });
@@ -0,0 +1,2 @@
1
+ @layer components {.surface-field{--color:var(--color-text-500);--surface-background:var(--color-white-300);--surface-border-color:oklch(from var(--color-black-300) l c h / .06);--surface-border-radius:14px;--surface-box-shadow:0 1px 2px oklch(from var(--color-black-300) l c h / .06), 0 8px 24px -8px oklch(from var(--color-black-300) l c h / .14);--surface-box-shadow-active:0 2px 4px oklch(from var(--color-black-300) l c h / .08), 0 20px 40px -12px oklch(from var(--color-black-300) l c h / .24);--surface-grip-color:var(--color-text-300);--surface-handle-height:28px;--surface-lift-duration:.2s;isolation:isolate;position:relative}.surface-field-canvas{color:var(--color);pointer-events:none;z-index:0;width:100%;height:100%;transition:none;position:absolute;inset:0}.surface-field-content{z-index:1;height:100%;position:relative}.surface-field-surface{background:var(--surface-background);border-radius:var(--surface-border-radius);box-shadow:0 0 0 1px var(--surface-border-color), var(--surface-box-shadow);transition:box-shadow var(--surface-lift-duration) ease, scale var(--surface-lift-duration) ease;flex-direction:column;display:flex;position:absolute;top:0;left:0}.surface-field-surface.--active{box-shadow:0 0 0 1px var(--surface-border-color), var(--surface-box-shadow-active);scale:1.01}.surface-field-surface-content{flex:1;min-height:0;padding:0 16px 16px;overflow:hidden}.surface-field-surface-handle,.surface-field-surface-resize{color:var(--surface-grip-color);touch-action:none;background:0 0;border:0;padding:0}.surface-field-surface-handle:focus-visible,.surface-field-surface-resize:focus-visible{outline:2px solid oklch(from var(--color) l c h/.4);outline-offset:-2px}.surface-field-surface-handle{border-radius:var(--surface-border-radius) var(--surface-border-radius) 0 0;cursor:grab;height:var(--surface-handle-height);flex-shrink:0;width:100%;position:relative}.surface-field-surface-handle:before{content:"";opacity:.7;background:currentColor;border-radius:999px;width:18px;height:2px;position:absolute;top:50%;left:50%;translate:-50% -50%}.surface-field-surface.--active .surface-field-surface-handle{cursor:grabbing}.surface-field-surface-resize{border-radius:0 0 var(--surface-border-radius) 0;cursor:nwse-resize;opacity:.7;background:linear-gradient(135deg,#0000 45%,currentColor 45% 52%,#0000 52%) 4px 4px/12px 12px no-repeat,linear-gradient(135deg,#0000 70%,currentColor 70% 77%,#0000 77%) 4px 4px/12px 12px no-repeat;width:22px;height:22px;position:absolute;bottom:0;right:0}@media (prefers-reduced-motion:reduce){.surface-field-surface{transition:box-shadow var(--surface-lift-duration) ease}.surface-field-surface.--active{scale:1}}}
2
+ /*$vite$:1*/
package/package.json CHANGED
@@ -58,7 +58,7 @@
58
58
  "**/*.scss"
59
59
  ],
60
60
  "type": "module",
61
- "version": "0.56.2",
61
+ "version": "0.56.4",
62
62
  "scripts": {
63
63
  "build": "run-s build:vite build:ts",
64
64
  "build:ts": "tsc",
@@ -130,8 +130,9 @@
130
130
  scale: 0.75;
131
131
  }
132
132
 
133
- // Wide enough for columns: the call to action waits below the card and the text lifts to make room for it.
134
- @container (min-width: 720px) {
133
+ // Wide enough for three ~180px columns: the call to action waits below the card and the text lifts to make room
134
+ // for it. Magic UI switches at the lg viewport, where its grid is around 700–900px; docs previews are narrower.
135
+ @container (min-width: 560px) {
135
136
  &-card {
136
137
  grid-column: span var(--span);
137
138
  }
@@ -50,6 +50,7 @@ export { default as modal } from './modal';
50
50
  export { default as morphingButton } from './morphing-button';
51
51
  export { default as morphingNav } from './morphing-nav';
52
52
  export { default as multiStepForm } from './multi-step-form';
53
+ export { default as navigationMenu } from './navigation-menu';
53
54
  export { default as nestedMenu } from './nested-menu';
54
55
  export { default as notificationBell } from './notification-bell';
55
56
  export { default as number } from './number';
@@ -58,6 +59,7 @@ export { default as overlay } from './overlay';
58
59
  export { default as pageDots } from './page-dots';
59
60
  export { default as pagination } from './pagination';
60
61
  export { default as password } from './password';
62
+ export { default as planCard } from './plan-card';
61
63
  export { default as progress } from './progress';
62
64
  export { default as pullToRefresh } from './pull-to-refresh';
63
65
  export { default as radio } from './radio';
@@ -92,6 +94,7 @@ export { default as statusPicker } from './status-picker';
92
94
  export { default as stickyHeader } from './sticky-header';
93
95
  export { default as stickyStack } from './sticky-stack';
94
96
  export { default as storyProgress } from './story-progress';
97
+ export { default as surfaceField } from './surface-field';
95
98
  export { default as swipeDeck } from './swipe-deck';
96
99
  export { default as switch } from './switch';
97
100
  export { default as tagInput } from './tag-input';