@birdycom/omniaui 0.11.2 → 0.12.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/dist/oc-theme.css CHANGED
@@ -1,4 +1,4 @@
1
- /* File: oc-theme.css — generated from tokens/semantic.json by @birdycom/omniacss 0.11.2. Do not edit. */
1
+ /* File: oc-theme.css — generated from tokens/semantic.json by @birdycom/omniacss 0.12.0. Do not edit. */
2
2
  /* Semantic theme tokens: every color is light-dark() of an Omnia palette token (oc-colors.css). */
3
3
  /* Same source as the desktop export: npx omniacss tokens --format json|dtcg|python */
4
4
  :root {
@@ -50,6 +50,8 @@
50
50
  background:
51
51
  radial-gradient(circle at 80% 20%, color-mix(in oklch, var(--color-white-50) 30%, transparent), transparent 45%),
52
52
  linear-gradient(135deg, var(--oc-accent-from), var(--oc-accent-to));
53
+ /* The hover zoom grows down and sideways (clipped by the frame), never up over the title bar. */
54
+ transform-origin: 50% 0;
53
55
  transition: scale 0.5s var(--oc-ease-out);
54
56
  }
55
57
 
package/dist/showcase.css CHANGED
@@ -48,7 +48,9 @@
48
48
  .oc-btn--pill { border-radius: 999px; }
49
49
  .oc-btn--gradient {
50
50
  border-radius: 999px;
51
- background: linear-gradient(100deg, var(--oc-accent-from), var(--oc-accent-to));
51
+ /* border-box: the gradient also runs under the transparent 1px border of .oc-btn; from the padding box it would
52
+ repeat in that border and show a thin stripe of the other end's color on both sides. */
53
+ background: linear-gradient(100deg, var(--oc-accent-from), var(--oc-accent-to)) border-box;
52
54
  color: var(--color-white-50);
53
55
  box-shadow: 0 10px 30px -10px var(--oc-accent-to);
54
56
  transition: transform 0.2s var(--oc-ease-out), box-shadow 0.2s;
@@ -238,16 +240,21 @@
238
240
  background: oklch(from var(--oc-accent-from) l c h / 0.14);
239
241
  color: light-dark(var(--oc-accent-from), oklch(from var(--oc-accent-from) max(l, 0.72) c h));
240
242
  }
243
+ /* Pulse: the ring starts at --oc-status-dot-pulse-alpha of the accent and grows to --oc-status-dot-pulse-size.
244
+ --strong starts at the full accent with a wider ring. */
241
245
  .oc-status-dot {
246
+ --oc-status-dot-pulse-alpha: 0.6;
247
+ --oc-status-dot-pulse-size: 8px;
242
248
  inline-size: 0.5rem;
243
249
  aspect-ratio: 1;
244
250
  border-radius: 50%;
245
251
  background: var(--oc-accent-from);
246
252
  animation: oc-pulse 2s infinite;
247
253
  }
254
+ .oc-status-dot--strong { --oc-status-dot-pulse-alpha: 1; --oc-status-dot-pulse-size: 10px; }
248
255
  @keyframes oc-pulse {
249
- 0% { box-shadow: 0 0 0 0 oklch(from var(--oc-accent-from) l c h / 0.6); }
250
- 70%, 100% { box-shadow: 0 0 0 8px transparent; }
256
+ 0% { box-shadow: 0 0 0 0 oklch(from var(--oc-accent-from) l c h / var(--oc-status-dot-pulse-alpha)); }
257
+ 70%, 100% { box-shadow: 0 0 0 var(--oc-status-dot-pulse-size) transparent; }
251
258
  }
252
259
 
253
260
  /* Stat strip: big numbers in a bordered row (pairs with .oc-counter for counting up) */
package/manifest.json CHANGED
@@ -1103,6 +1103,14 @@
1103
1103
  "requires": [
1104
1104
  "@birdycom/omniaui"
1105
1105
  ]
1106
+ },
1107
+ {
1108
+ "name": "carousel-loop",
1109
+ "file": "snippets/carousel-loop.html",
1110
+ "description": "Looping carousel: after the last slide the next button goes back to the first",
1111
+ "requires": [
1112
+ "@birdycom/omniaui"
1113
+ ]
1106
1114
  }
1107
1115
  ]
1108
1116
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@birdycom/omniaui",
3
- "version": "0.11.2",
3
+ "version": "0.12.0",
4
4
  "description": "OmniaUI components: CSS-first UI built on native HTML (dialog, popover, details) with light-dark() theming — no JavaScript required. Includes the omniaui CLI (add/list).",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -29,6 +29,7 @@
29
29
  "./showcase.css": "./dist/showcase.css",
30
30
  "./snippets/*": "./snippets/*",
31
31
  "./data-table.js": "./dist/data-table.js",
32
+ "./carousel.js": "./dist/carousel.js",
32
33
  "./manifest.json": "./manifest.json",
33
34
  "./package.json": "./package.json"
34
35
  },
@@ -56,7 +57,7 @@
56
57
  "omniaui": "./bin/omniaui.mjs"
57
58
  },
58
59
  "peerDependencies": {
59
- "@birdycom/omniacss": "^0.11.2"
60
+ "@birdycom/omniacss": "^0.12.0"
60
61
  },
61
62
  "peerDependenciesMeta": {
62
63
  "@birdycom/omniacss": {
@@ -0,0 +1,20 @@
1
+ <!-- OmniaUI component: carousel-loop - Looping carousel: after the last slide the next button goes back to the first. Needs @birdycom/omniaui CSS and @birdycom/omniaui/carousel.js.
2
+ Class API: .oc-carousel--loop on the carousel, with .oc-carousel-prev / .oc-carousel-next buttons.
3
+ Script: import { initCarousels } from "@birdycom/omniaui/carousel.js"; initCarousels();
4
+ Without the script the buttons stay hidden and the CSS arrows (which stop at the ends) remain. -->
5
+ <div class="oc-carousel oc-carousel--loop">
6
+ <div class="oc-carousel-viewport" id="loop-carousel" tabindex="0" role="region" aria-roledescription="carousel" aria-label="Highlights">
7
+ <div class="oc-carousel-item" id="loop-slide-1" role="group" aria-roledescription="slide" aria-label="1 of 4">Slide 1</div>
8
+ <div class="oc-carousel-item" id="loop-slide-2" role="group" aria-roledescription="slide" aria-label="2 of 4">Slide 2</div>
9
+ <div class="oc-carousel-item" id="loop-slide-3" role="group" aria-roledescription="slide" aria-label="3 of 4">Slide 3</div>
10
+ <div class="oc-carousel-item" id="loop-slide-4" role="group" aria-roledescription="slide" aria-label="4 of 4">Slide 4</div>
11
+ </div>
12
+ <button class="oc-carousel-prev" type="button" aria-controls="loop-carousel" aria-label="Previous slide">&larr;</button>
13
+ <button class="oc-carousel-next" type="button" aria-controls="loop-carousel" aria-label="Next slide">&rarr;</button>
14
+ <nav class="oc-carousel-dots" aria-label="Choose a slide">
15
+ <a class="oc-carousel-dot" href="#loop-slide-1" aria-label="Slide 1"></a>
16
+ <a class="oc-carousel-dot" href="#loop-slide-2" aria-label="Slide 2"></a>
17
+ <a class="oc-carousel-dot" href="#loop-slide-3" aria-label="Slide 3"></a>
18
+ <a class="oc-carousel-dot" href="#loop-slide-4" aria-label="Slide 4"></a>
19
+ </nav>
20
+ </div>
@@ -47,4 +47,17 @@ document.addEventListener("command", (e) => {
47
47
  const id = e.source?.dataset.ocLightboxSlide;
48
48
  if (id) requestAnimationFrame(() => document.getElementById(id)?.scrollIntoView({ behavior: "instant", block: "nearest", inline: "center" }));
49
49
  }, true);
50
+ // Optional: prev / next scroll without putting #slide in the address and the history (without this script they
51
+ // are plain links), and closing removes a slide hash of this viewer from the address.
52
+ document.addEventListener("click", (e) => {
53
+ const nav = e.target.closest?.("dialog.oc-lightbox a.oc-lightbox__nav");
54
+ const slide = nav && document.getElementById(decodeURIComponent(nav.hash.slice(1)));
55
+ if (!slide) return;
56
+ e.preventDefault();
57
+ slide.scrollIntoView({ behavior: matchMedia("(prefers-reduced-motion: reduce)").matches ? "instant" : "smooth", block: "nearest", inline: "center" });
58
+ });
59
+ document.addEventListener("close", (e) => {
60
+ const slide = e.target.matches?.("dialog.oc-lightbox") && location.hash && document.getElementById(decodeURIComponent(location.hash.slice(1)));
61
+ if (slide && e.target.contains(slide)) history.replaceState(history.state, "", location.pathname + location.search);
62
+ }, true);
50
63
  </script>