@muten/shadcn 0.2.2 → 0.2.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.
- package/kit.css +10 -2
- package/package.json +1 -1
- package/registry/agenda.js +11 -3
- package/registry/carousel.muten +4 -3
- package/registry/modal-behavior.js +4 -2
package/kit.css
CHANGED
|
@@ -370,8 +370,10 @@ button.cn-item { width: 100%; font: inherit; text-align: left; cursor: pointer;
|
|
|
370
370
|
shows nothing: the agenda behind is the context */
|
|
371
371
|
.cx-modal[data-mode="anchor"] { width: min(24rem, calc(100% - 2rem)); max-height: min(38rem, calc(100dvh - 2rem)); border-radius: calc(var(--radius) * 1.4); overflow: hidden;
|
|
372
372
|
box-shadow: 0 0 0 1px color-mix(in srgb, var(--foreground) 10%, transparent), 0 24px 60px -20px rgb(20 16 40 / .38);
|
|
373
|
-
transform: scale
|
|
374
|
-
|
|
373
|
+
transform: none; scale: .96; opacity: 0; transition: scale calc(var(--t-modal) * .5) ease, opacity calc(var(--t-modal) * .4) ease; }
|
|
374
|
+
/* it grows in place with `scale`, never `transform`: a modal that was a sheet sits off-screen by its transform, and
|
|
375
|
+
animating that would fly the card in from the side */
|
|
376
|
+
.cx-modal-root[data-open="true"] > .cx-modal[data-mode="anchor"] { scale: 1; opacity: 1; transition: scale var(--t-pop, 180ms) var(--ease-out), opacity var(--t-pop, 180ms) var(--ease-out); }
|
|
375
377
|
.cx-modal-root:has(> .cx-modal[data-mode="anchor"]) > .cx-overlay { background: transparent; backdrop-filter: none; }
|
|
376
378
|
/* teléfono = Drawer desde abajo, arrastrable */
|
|
377
379
|
.cx-modal[data-mode="drawer"] { left: 0; right: 0; bottom: 0; margin-inline: auto; width: min(100%, 34rem); max-height: calc(100dvh - 3rem); border-radius: calc(var(--radius) * 1.8) calc(var(--radius) * 1.8) 0 0; overflow: hidden;
|
|
@@ -1494,6 +1496,12 @@ p.cx-text { margin: 0; }
|
|
|
1494
1496
|
.cx-thumb[aria-pressed="true"] { background: transparent; box-shadow: 0 0 0 2px var(--selected); }
|
|
1495
1497
|
.cx-car-card .cn-card-header { padding: 12px 12px 4px; }
|
|
1496
1498
|
@media (max-width: 640px) { .cx-car { --per: var(--per-sm) !important; } }
|
|
1499
|
+
/* only: "phone": swiped on a phone; on anything wider the same slides stand still in a grid of the wide perView, with
|
|
1500
|
+
no dots and no arrows (data-only is on the root from the first paint, so a wide screen never sees a track) */
|
|
1501
|
+
@media (min-width: 641px) {
|
|
1502
|
+
.cx-car[data-only="phone"] .cx-car-track { grid-auto-flow: row; grid-auto-columns: auto; grid-template-columns: repeat(var(--per, 3), minmax(0, 1fr)); overflow: visible; scroll-snap-type: none; padding-block: 0; margin-block: 0; }
|
|
1503
|
+
.cx-car[data-only="phone"] .cx-car-bar, .cx-car[data-only="phone"] .cx-car-arrow { display: none; }
|
|
1504
|
+
}
|
|
1497
1505
|
|
|
1498
1506
|
/* filters on the phone: search fills the row, «Filtros» beside it; chips scroll sideways */
|
|
1499
1507
|
.cx-dt-host:has(.cx-fbtn-m) .cx-dt-tools { width: 100%; flex-wrap: nowrap; }
|
package/package.json
CHANGED
package/registry/agenda.js
CHANGED
|
@@ -72,9 +72,17 @@ export function mount(el, inputs, on) {
|
|
|
72
72
|
};
|
|
73
73
|
map = data;
|
|
74
74
|
const send = (name, value) => on[name]?.(typeof value === 'string' ? value : JSON.stringify(value));
|
|
75
|
-
// WHERE A CITA IS ON SCREEN ("x,y,w,h"), so the app can open it beside itself (Modal mode "anchor"): the
|
|
76
|
-
// or row that
|
|
77
|
-
|
|
75
|
+
// WHERE A CITA IS ON SCREEN ("x,y,w,h"), so the app can open it beside itself (Modal mode "anchor"): the very chip,
|
|
76
|
+
// or row that was tapped; else its chip or row (never the «now» card: a band as wide as the agenda, nothing to sit by);
|
|
77
|
+
// '' when none is visible (opened from a command)
|
|
78
|
+
let tapped = null;
|
|
79
|
+
el.addEventListener('click', (e) => { tapped = e.target.closest?.('[data-ev]') ?? null; }, true);
|
|
80
|
+
const boxOf = (x) => { const r = x?.getBoundingClientRect(); return r && r.width > 0 && r.height > 0 ? [r.left, r.top, r.width, r.height].map(Math.round).join(',') : ''; };
|
|
81
|
+
const whereIs = (id) => {
|
|
82
|
+
if (tapped?.isConnected && !tapped.matches('.cx-ag-nowcard') && tapped.dataset.ev === String(id) && boxOf(tapped)) return boxOf(tapped);
|
|
83
|
+
const own = [...el.querySelectorAll(`.cx-ag-ev[data-ev="${CSS.escape(String(id))}"], .cx-ag-row[data-ev="${CSS.escape(String(id))}"]`)].map(boxOf).find(Boolean);
|
|
84
|
+
return own ?? '';
|
|
85
|
+
};
|
|
78
86
|
const day1 = (x) => ({ ...x, day: x.day instanceof Date ? iso(x.day) : x.day });
|
|
79
87
|
el.innerHTML = '';
|
|
80
88
|
api = kit.agenda(el, {
|
package/registry/carousel.muten
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
# Carousel - one component, options instead of copies. The slides are your muten content (CarouselSlide).
|
|
2
2
|
# perView "4" or "2,4" (phone, wider) · center "on" (the active one centred, neighbours peeking) · loop "on" ·
|
|
3
3
|
# autoplay ms (pauses on hover, focus, touch, hidden tab; off with reduced motion; its own pause button) ·
|
|
4
|
-
# indicator dots | progress | count | thumbs · arrows bar | overlay
|
|
4
|
+
# indicator dots | progress | count | thumbs · arrows bar | overlay | none ·
|
|
5
|
+
# only "phone" (a carousel on a phone; on a wider screen the same slides sit still in a grid of perView's wide count)
|
|
5
6
|
# Carousel(label: "Products", perView: "2,4") { each products as p { CarouselSlide { … } } }
|
|
6
7
|
# shadcn-for-muten · part + Custom (CarouselBehavior, kit collections) · kit.css (.cx-car).
|
|
7
|
-
part Carousel(label: text, perView: text = "1", center: text = "", loop: text = "", autoplay: number = 0, indicator: text = "dots", arrows: text = "bar") {
|
|
8
|
-
Section class("cx-car") aria(label: $label, roledescription: "carrusel") {
|
|
8
|
+
part Carousel(label: text, perView: text = "1", center: text = "", loop: text = "", autoplay: number = 0, indicator: text = "dots", arrows: text = "bar", only: text = "") {
|
|
9
|
+
Section class("cx-car") data(only: $only) aria(label: $label, roledescription: "carrusel") {
|
|
9
10
|
Stack class("cx-car-view") { Stack class("cx-car-track") { slot } }
|
|
10
11
|
Custom Carousel inputs(perView: $perView, center: $center, loop: $loop, autoplay: $autoplay, indicator: $indicator, arrows: $arrows) class("cx-car-behavior")
|
|
11
12
|
}
|
|
@@ -21,9 +21,11 @@ export function mount(el, inputs, on) {
|
|
|
21
21
|
let anchor = String(inputs.anchor || '');
|
|
22
22
|
// `want` is the mode the page asked for; `mode` is what it is now (an anchor with nothing to hold on to is a dialog)
|
|
23
23
|
const wantsAnchor = () => mdl.dataset.want === 'anchor';
|
|
24
|
+
// what an earlier opening as a card left on the element: a sheet or a dialog opened next must not keep it
|
|
25
|
+
const unplace = () => { mdl.style.left = ''; mdl.style.top = ''; mdl.style.transformOrigin = ''; };
|
|
24
26
|
const place = () => {
|
|
25
27
|
const at = anchor.split(',').map(Number);
|
|
26
|
-
if (!wantsAnchor() || phone.matches || at.length !== 4 || at.some((n) => !Number.isFinite(n))) { if (wantsAnchor()) mdl.dataset.mode = phone.matches ? 'drawer' : 'dialog'; return; }
|
|
28
|
+
if (!wantsAnchor() || phone.matches || at.length !== 4 || at.some((n) => !Number.isFinite(n))) { unplace(); if (wantsAnchor()) mdl.dataset.mode = phone.matches ? 'drawer' : 'dialog'; return; }
|
|
27
29
|
mdl.dataset.mode = 'anchor';
|
|
28
30
|
const [x, y, w] = at, gap = 12, edge = 16;
|
|
29
31
|
const width = mdl.offsetWidth, height = Math.min(mdl.scrollHeight, innerHeight - edge * 2);
|
|
@@ -36,7 +38,7 @@ export function mount(el, inputs, on) {
|
|
|
36
38
|
const open = () => {
|
|
37
39
|
if (isOpen) return; isOpen = true; placeFooter();
|
|
38
40
|
if (auto) mdl.dataset.mode = phone.matches ? 'drawer' : 'dialog';
|
|
39
|
-
if (wantsAnchor()) place();
|
|
41
|
+
if (wantsAnchor()) place(); else unplace();
|
|
40
42
|
lastFocus = document.activeElement;
|
|
41
43
|
document.documentElement.classList.add('cx-locked');
|
|
42
44
|
// on the phone, focusing a field would throw the keyboard over the sheet: focus the sheet itself
|