@jomae/catalog 0.1.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.
Files changed (119) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +61 -0
  3. package/dist/baseline.d.ts +51 -0
  4. package/dist/baseline.d.ts.map +1 -0
  5. package/dist/baseline.js +123 -0
  6. package/dist/baseline.js.map +1 -0
  7. package/dist/detect.d.ts +81 -0
  8. package/dist/detect.d.ts.map +1 -0
  9. package/dist/detect.js +155 -0
  10. package/dist/detect.js.map +1 -0
  11. package/dist/format.d.ts +20 -0
  12. package/dist/format.d.ts.map +1 -0
  13. package/dist/format.js +45 -0
  14. package/dist/format.js.map +1 -0
  15. package/dist/generated/baseline.d.ts +22 -0
  16. package/dist/generated/baseline.d.ts.map +1 -0
  17. package/dist/generated/baseline.js +240 -0
  18. package/dist/generated/baseline.js.map +1 -0
  19. package/dist/generated/sizes.d.ts +18 -0
  20. package/dist/generated/sizes.d.ts.map +1 -0
  21. package/dist/generated/sizes.js +474 -0
  22. package/dist/generated/sizes.js.map +1 -0
  23. package/dist/index.d.ts +13 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +13 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/rules/accordion.d.ts +3 -0
  28. package/dist/rules/accordion.d.ts.map +1 -0
  29. package/dist/rules/accordion.js +50 -0
  30. package/dist/rules/accordion.js.map +1 -0
  31. package/dist/rules/aspect-ratio.d.ts +3 -0
  32. package/dist/rules/aspect-ratio.d.ts.map +1 -0
  33. package/dist/rules/aspect-ratio.js +33 -0
  34. package/dist/rules/aspect-ratio.js.map +1 -0
  35. package/dist/rules/carousel.d.ts +3 -0
  36. package/dist/rules/carousel.d.ts.map +1 -0
  37. package/dist/rules/carousel.js +78 -0
  38. package/dist/rules/carousel.js.map +1 -0
  39. package/dist/rules/color-functions.d.ts +3 -0
  40. package/dist/rules/color-functions.d.ts.map +1 -0
  41. package/dist/rules/color-functions.js +42 -0
  42. package/dist/rules/color-functions.js.map +1 -0
  43. package/dist/rules/container-queries.d.ts +3 -0
  44. package/dist/rules/container-queries.d.ts.map +1 -0
  45. package/dist/rules/container-queries.js +53 -0
  46. package/dist/rules/container-queries.js.map +1 -0
  47. package/dist/rules/dialog.d.ts +3 -0
  48. package/dist/rules/dialog.d.ts.map +1 -0
  49. package/dist/rules/dialog.js +51 -0
  50. package/dist/rules/dialog.js.map +1 -0
  51. package/dist/rules/discrete-transitions.d.ts +3 -0
  52. package/dist/rules/discrete-transitions.d.ts.map +1 -0
  53. package/dist/rules/discrete-transitions.js +57 -0
  54. package/dist/rules/discrete-transitions.js.map +1 -0
  55. package/dist/rules/field-sizing.d.ts +3 -0
  56. package/dist/rules/field-sizing.d.ts.map +1 -0
  57. package/dist/rules/field-sizing.js +37 -0
  58. package/dist/rules/field-sizing.js.map +1 -0
  59. package/dist/rules/fluid-type.d.ts +3 -0
  60. package/dist/rules/fluid-type.d.ts.map +1 -0
  61. package/dist/rules/fluid-type.js +30 -0
  62. package/dist/rules/fluid-type.js.map +1 -0
  63. package/dist/rules/height-animation.d.ts +3 -0
  64. package/dist/rules/height-animation.d.ts.map +1 -0
  65. package/dist/rules/height-animation.js +46 -0
  66. package/dist/rules/height-animation.js.map +1 -0
  67. package/dist/rules/index.d.ts +14 -0
  68. package/dist/rules/index.d.ts.map +1 -0
  69. package/dist/rules/index.js +56 -0
  70. package/dist/rules/index.js.map +1 -0
  71. package/dist/rules/masonry.d.ts +3 -0
  72. package/dist/rules/masonry.d.ts.map +1 -0
  73. package/dist/rules/masonry.js +56 -0
  74. package/dist/rules/masonry.js.map +1 -0
  75. package/dist/rules/popover.d.ts +3 -0
  76. package/dist/rules/popover.d.ts.map +1 -0
  77. package/dist/rules/popover.js +62 -0
  78. package/dist/rules/popover.js.map +1 -0
  79. package/dist/rules/scroll-animations.d.ts +3 -0
  80. package/dist/rules/scroll-animations.d.ts.map +1 -0
  81. package/dist/rules/scroll-animations.js +58 -0
  82. package/dist/rules/scroll-animations.js.map +1 -0
  83. package/dist/rules/scroll-lock.d.ts +3 -0
  84. package/dist/rules/scroll-lock.d.ts.map +1 -0
  85. package/dist/rules/scroll-lock.js +40 -0
  86. package/dist/rules/scroll-lock.js.map +1 -0
  87. package/dist/rules/scrollbars.d.ts +3 -0
  88. package/dist/rules/scrollbars.d.ts.map +1 -0
  89. package/dist/rules/scrollbars.js +44 -0
  90. package/dist/rules/scrollbars.js.map +1 -0
  91. package/dist/rules/select.d.ts +3 -0
  92. package/dist/rules/select.d.ts.map +1 -0
  93. package/dist/rules/select.js +54 -0
  94. package/dist/rules/select.js.map +1 -0
  95. package/dist/rules/smooth-scroll.d.ts +3 -0
  96. package/dist/rules/smooth-scroll.d.ts.map +1 -0
  97. package/dist/rules/smooth-scroll.js +41 -0
  98. package/dist/rules/smooth-scroll.js.map +1 -0
  99. package/dist/rules/sticky.d.ts +3 -0
  100. package/dist/rules/sticky.d.ts.map +1 -0
  101. package/dist/rules/sticky.js +39 -0
  102. package/dist/rules/sticky.js.map +1 -0
  103. package/dist/rules/text-box-trim.d.ts +3 -0
  104. package/dist/rules/text-box-trim.d.ts.map +1 -0
  105. package/dist/rules/text-box-trim.js +32 -0
  106. package/dist/rules/text-box-trim.js.map +1 -0
  107. package/dist/rules/text-wrap-balance.d.ts +3 -0
  108. package/dist/rules/text-wrap-balance.d.ts.map +1 -0
  109. package/dist/rules/text-wrap-balance.js +34 -0
  110. package/dist/rules/text-wrap-balance.js.map +1 -0
  111. package/dist/rules/view-transitions.d.ts +3 -0
  112. package/dist/rules/view-transitions.d.ts.map +1 -0
  113. package/dist/rules/view-transitions.js +53 -0
  114. package/dist/rules/view-transitions.js.map +1 -0
  115. package/dist/schema.d.ts +91 -0
  116. package/dist/schema.d.ts.map +1 -0
  117. package/dist/schema.js +124 -0
  118. package/dist/schema.js.map +1 -0
  119. package/package.json +52 -0
@@ -0,0 +1,56 @@
1
+ export const masonry = {
2
+ id: "css-masonry",
3
+ title: "Masonry layouts",
4
+ replaces: [
5
+ "react-masonry-css",
6
+ "masonry-layout",
7
+ "react-masonry-component",
8
+ "muuri",
9
+ "react-photo-gallery",
10
+ ],
11
+ featureIds: ["masonry"],
12
+ native: "CSS masonry item placement",
13
+ human: {
14
+ explainer: "A masonry library reads every item's height and absolutely positions it into the shortest column, then redoes the whole thing on resize. CSS masonry places items into the shortest track during layout, so it stays correct on resize with no JavaScript and keeps items in DOM order for keyboard and screen reader users, which absolutely positioned columns often do not. This is the least settled feature in the catalog: the syntax has changed more than once and is still being argued about, so treat it as something to try rather than something to ship.",
15
+ snippet: `.gallery {
16
+ display: grid;
17
+ grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
18
+ grid-template-rows: masonry;
19
+ gap: 1rem;
20
+ }
21
+
22
+ /* A column-based fallback that works everywhere. Reading order
23
+ goes down each column rather than across, which is the
24
+ trade-off you accept for shipping it today. */
25
+ @supports not (grid-template-rows: masonry) {
26
+ .gallery {
27
+ display: block;
28
+ columns: 16rem;
29
+ column-gap: 1rem;
30
+ }
31
+ .gallery > * {
32
+ break-inside: avoid;
33
+ margin-bottom: 1rem;
34
+ }
35
+ }`,
36
+ },
37
+ agent: {
38
+ when: "laying out a gallery of items with varying heights into columns with no vertical gaps",
39
+ unless: [
40
+ "You are shipping to production. Masonry is limited availability, the syntax is not final, and it may land under a different property name. Use the CSS columns fallback or keep the library.",
41
+ "You need drag-and-drop reordering or filtering with animated repositioning.",
42
+ "You need items to span multiple columns based on their content.",
43
+ "Reading order matters and you need it to go across rows rather than down columns, which the columns fallback cannot do.",
44
+ ],
45
+ snippet: `.gallery {
46
+ display: grid;
47
+ grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
48
+ grid-template-rows: masonry;
49
+ }
50
+ @supports not (grid-template-rows: masonry) {
51
+ .gallery { columns: 16rem; }
52
+ .gallery > * { break-inside: avoid; }
53
+ }`,
54
+ },
55
+ };
56
+ //# sourceMappingURL=masonry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"masonry.js","sourceRoot":"","sources":["../../src/rules/masonry.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,OAAO,GAAS;IAC3B,EAAE,EAAE,aAAa;IACjB,KAAK,EAAE,iBAAiB;IACxB,QAAQ,EAAE;QACR,mBAAmB;QACnB,gBAAgB;QAChB,yBAAyB;QACzB,OAAO;QACP,qBAAqB;KACtB;IACD,UAAU,EAAE,CAAC,SAAS,CAAC;IACvB,MAAM,EAAE,4BAA4B;IACpC,KAAK,EAAE;QACL,SAAS,EACP,wiBAAwiB;QAC1iB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;EAoBX;KACC;IACD,KAAK,EAAE;QACL,IAAI,EAAE,uFAAuF;QAC7F,MAAM,EAAE;YACN,8LAA8L;YAC9L,6EAA6E;YAC7E,iEAAiE;YACjE,yHAAyH;SAC1H;QACD,OAAO,EAAE;;;;;;;;EAQX;KACC;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Rule } from "../schema.ts";
2
+ export declare const popover: Rule;
3
+ //# sourceMappingURL=popover.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"popover.d.ts","sourceRoot":"","sources":["../../src/rules/popover.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,OAAO,EAAE,IA6DrB,CAAC"}
@@ -0,0 +1,62 @@
1
+ export const popover = {
2
+ id: "popover-anchor-positioning",
3
+ title: "Tooltips, dropdowns and popovers",
4
+ replaces: [
5
+ "@floating-ui/react",
6
+ "@floating-ui/react-dom",
7
+ "@floating-ui/dom",
8
+ "@popperjs/core",
9
+ "popper.js",
10
+ "tippy.js",
11
+ "@tippyjs/react",
12
+ "react-popper",
13
+ "react-tooltip",
14
+ ],
15
+ featureIds: ["popover", "anchor-positioning"],
16
+ native: "The Popover API with CSS anchor positioning",
17
+ human: {
18
+ explainer: "Two separate problems used to need a library. Putting an element in the top layer so it escapes overflow and z-index, and keeping it pinned to its trigger. The popover attribute solves the first, including light dismiss, Escape to close and focus handling, with no JavaScript at all. CSS anchor positioning solves the second, including position-try fallbacks that flip the popover when it would overflow the viewport. Anchor positioning is the part to check before you commit, because it has not reached Baseline yet.",
19
+ snippet: `<button popovertarget="menu" id="trigger">Open</button>
20
+ <div popover id="menu">Anchored content</div>
21
+
22
+ <style>
23
+ #trigger {
24
+ anchor-name: --trigger;
25
+ }
26
+
27
+ #menu {
28
+ position: absolute;
29
+ position-anchor: --trigger;
30
+ /* Sit below the trigger, aligned to its left edge. */
31
+ top: anchor(bottom);
32
+ left: anchor(left);
33
+ margin-top: 0.5rem;
34
+ /* Flip above when there is no room below. */
35
+ position-try-fallbacks: flip-block;
36
+ }
37
+ </style>`,
38
+ demoUrl: "https://www.jomaendle.com/blog/html-popover",
39
+ },
40
+ agent: {
41
+ when: "building a tooltip, dropdown menu or popover anchored to a trigger",
42
+ unless: [
43
+ "You need Baseline-level support for the positioning. CSS anchor positioning is Chromium-only today, so Safari and Firefox need a JavaScript fallback or a static position.",
44
+ "You need collision handling beyond position-try-fallbacks, such as shifting along an axis to stay in view rather than flipping.",
45
+ "You need an arrow that tracks the trigger across a flip.",
46
+ "A popover must stay open while a second one opens, or nest inside another. Auto popovers close their ancestors.",
47
+ "You need hover-with-intent timing, which the platform does not cover.",
48
+ ],
49
+ snippet: `<button popovertarget="p" id="t">Open</button>
50
+ <div popover id="p">Content</div>
51
+ <style>
52
+ #t { anchor-name: --t; }
53
+ #p {
54
+ position: absolute;
55
+ position-anchor: --t;
56
+ top: anchor(bottom);
57
+ position-try-fallbacks: flip-block;
58
+ }
59
+ </style>`,
60
+ },
61
+ };
62
+ //# sourceMappingURL=popover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"popover.js","sourceRoot":"","sources":["../../src/rules/popover.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,OAAO,GAAS;IAC3B,EAAE,EAAE,4BAA4B;IAChC,KAAK,EAAE,kCAAkC;IACzC,QAAQ,EAAE;QACR,oBAAoB;QACpB,wBAAwB;QACxB,kBAAkB;QAClB,gBAAgB;QAChB,WAAW;QACX,UAAU;QACV,gBAAgB;QAChB,cAAc;QACd,eAAe;KAChB;IACD,UAAU,EAAE,CAAC,SAAS,EAAE,oBAAoB,CAAC;IAC7C,MAAM,EAAE,6CAA6C;IACrD,KAAK,EAAE;QACL,SAAS,EACP,ugBAAugB;QACzgB,OAAO,EAAE;;;;;;;;;;;;;;;;;;SAkBJ;QACL,OAAO,EAAE,6CAA6C;KACvD;IACD,KAAK,EAAE;QACL,IAAI,EAAE,oEAAoE;QAC1E,MAAM,EAAE;YACN,4KAA4K;YAC5K,iIAAiI;YACjI,0DAA0D;YAC1D,iHAAiH;YACjH,uEAAuE;SACxE;QACD,OAAO,EAAE;;;;;;;;;;SAUJ;KACN;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Rule } from "../schema.ts";
2
+ export declare const scrollAnimations: Rule;
3
+ //# sourceMappingURL=scroll-animations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scroll-animations.d.ts","sourceRoot":"","sources":["../../src/rules/scroll-animations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,gBAAgB,EAAE,IAyD9B,CAAC"}
@@ -0,0 +1,58 @@
1
+ export const scrollAnimations = {
2
+ id: "scroll-driven-animations",
3
+ title: "Scroll-triggered animations",
4
+ replaces: ["aos", "scrollreveal", "wowjs", "wow.js", "scrollmagic", "rellax"],
5
+ featureIds: ["scroll-driven-animations"],
6
+ native: "animation-timeline: view() and scroll()",
7
+ human: {
8
+ explainer: "Reveal-on-scroll libraries watch elements with an IntersectionObserver and add a class. animation-timeline replaces the observer with a timeline: view() ties an animation's progress to the element's position in the viewport, and scroll() ties it to a scroll container's offset. These run off the main thread, so they hold up under load in a way that a scroll listener does not. Fade-in-on-scroll is a progressive enhancement, so the fallback is simply that the content is visible, which is the correct default anyway.",
9
+ snippet: `@keyframes fade-in {
10
+ from {
11
+ opacity: 0;
12
+ translate: 0 2rem;
13
+ }
14
+ }
15
+
16
+ @media (prefers-reduced-motion: no-preference) {
17
+ @supports (animation-timeline: view()) {
18
+ .reveal {
19
+ animation: fade-in linear both;
20
+ animation-timeline: view();
21
+ /* Run from entering the viewport to 40% up it. */
22
+ animation-range: entry 0% cover 40%;
23
+ }
24
+ }
25
+ }
26
+
27
+ /* A reading-progress bar, no JavaScript. */
28
+ @keyframes grow {
29
+ from {
30
+ scale: 0 1;
31
+ }
32
+ }
33
+ .progress {
34
+ animation: grow linear both;
35
+ animation-timeline: scroll(root block);
36
+ transform-origin: left;
37
+ }`,
38
+ },
39
+ agent: {
40
+ when: "fading or moving elements in as they scroll into view, or driving a reading-progress bar",
41
+ unless: [
42
+ "You need Safari or Firefox support. Scroll-driven animations are limited availability, so wrap them in @supports and make sure the un-animated state is the visible one.",
43
+ "You need a callback in JavaScript when an element enters view, for analytics, lazy loading or infinite scroll. That is what IntersectionObserver is for and CSS does not replace it.",
44
+ "You need to animate something that is not a descendant of, or a sibling reachable from, the scrolling element. Timeline scope is limited.",
45
+ "The animation must run once and stay put. A view timeline is scrubbed, so it reverses when the user scrolls back up.",
46
+ "You are using the library's IntersectionObserver for anything other than animation, in which case removing it changes unrelated behaviour.",
47
+ ],
48
+ snippet: `@keyframes fade-in { from { opacity: 0; translate: 0 2rem; } }
49
+ @supports (animation-timeline: view()) {
50
+ .reveal {
51
+ animation: fade-in linear both;
52
+ animation-timeline: view();
53
+ animation-range: entry 0% cover 40%;
54
+ }
55
+ }`,
56
+ },
57
+ };
58
+ //# sourceMappingURL=scroll-animations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scroll-animations.js","sourceRoot":"","sources":["../../src/rules/scroll-animations.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,gBAAgB,GAAS;IACpC,EAAE,EAAE,0BAA0B;IAC9B,KAAK,EAAE,6BAA6B;IACpC,QAAQ,EAAE,CAAC,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,QAAQ,CAAC;IAC7E,UAAU,EAAE,CAAC,0BAA0B,CAAC;IACxC,MAAM,EAAE,yCAAyC;IACjD,KAAK,EAAE;QACL,SAAS,EACP,ugBAAugB;QACzgB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4BX;KACC;IACD,KAAK,EAAE;QACL,IAAI,EAAE,0FAA0F;QAChG,MAAM,EAAE;YACN,0KAA0K;YAC1K,sLAAsL;YACtL,2IAA2I;YAC3I,sHAAsH;YACtH,4IAA4I;SAC7I;QACD,OAAO,EAAE;;;;;;;EAOX;KACC;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Rule } from "../schema.ts";
2
+ export declare const scrollLock: Rule;
3
+ //# sourceMappingURL=scroll-lock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scroll-lock.d.ts","sourceRoot":"","sources":["../../src/rules/scroll-lock.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,UAAU,EAAE,IAuCxB,CAAC"}
@@ -0,0 +1,40 @@
1
+ export const scrollLock = {
2
+ id: "overscroll-behavior",
3
+ title: "Scroll chaining and body scroll lock",
4
+ replaces: [
5
+ "body-scroll-lock",
6
+ "react-scrolllock",
7
+ "no-scroll",
8
+ "scroll-lock",
9
+ ],
10
+ featureIds: ["overscroll-behavior"],
11
+ native: "overscroll-behavior: contain",
12
+ human: {
13
+ explainer: "Reaching the end of a scrollable modal and having the page behind it start scrolling is scroll chaining. overscroll-behavior: contain stops the scroll at that boundary, which is the behaviour body-scroll-lock reimplements by fixing the body and compensating for the scrollbar. contain also disables pull-to-refresh inside that element, which is usually what you want in a drawer. Note that a modal opened with showModal() already blocks background scrolling, so check whether you need this at all.",
14
+ snippet: `.drawer,
15
+ .modal-body {
16
+ overflow-y: auto;
17
+ /* Stop the page behind from scrolling at the boundary. */
18
+ overscroll-behavior: contain;
19
+ }
20
+
21
+ /* Disable pull-to-refresh for the whole page. */
22
+ body {
23
+ overscroll-behavior-y: contain;
24
+ }`,
25
+ },
26
+ agent: {
27
+ when: "stopping the page behind a modal or drawer from scrolling when the overlay reaches its end",
28
+ unless: [
29
+ "You need this to work everywhere today. web-features reports overscroll-behavior as limited availability, so verify against your support target rather than assuming it.",
30
+ "You need the background genuinely frozen, not just unchained. iOS Safari in particular has a long history of scrolling the body anyway, which is the specific bug body-scroll-lock exists to work around.",
31
+ "The overlay itself does not scroll. overscroll-behavior only applies to a scroll container, so a short modal needs a different approach.",
32
+ "You need to preserve and restore the scroll position across opening and closing.",
33
+ ],
34
+ snippet: `.drawer {
35
+ overflow-y: auto;
36
+ overscroll-behavior: contain;
37
+ }`,
38
+ },
39
+ };
40
+ //# sourceMappingURL=scroll-lock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scroll-lock.js","sourceRoot":"","sources":["../../src/rules/scroll-lock.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,UAAU,GAAS;IAC9B,EAAE,EAAE,qBAAqB;IACzB,KAAK,EAAE,sCAAsC;IAC7C,QAAQ,EAAE;QACR,kBAAkB;QAClB,kBAAkB;QAClB,WAAW;QACX,aAAa;KACd;IACD,UAAU,EAAE,CAAC,qBAAqB,CAAC;IACnC,MAAM,EAAE,8BAA8B;IACtC,KAAK,EAAE;QACL,SAAS,EACP,mfAAmf;QACrf,OAAO,EAAE;;;;;;;;;;EAUX;KACC;IACD,KAAK,EAAE;QACL,IAAI,EAAE,4FAA4F;QAClG,MAAM,EAAE;YACN,0KAA0K;YAC1K,2MAA2M;YAC3M,0IAA0I;YAC1I,kFAAkF;SACnF;QACD,OAAO,EAAE;;;EAGX;KACC;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Rule } from "../schema.ts";
2
+ export declare const scrollbars: Rule;
3
+ //# sourceMappingURL=scrollbars.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scrollbars.d.ts","sourceRoot":"","sources":["../../src/rules/scrollbars.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,UAAU,EAAE,IA2CxB,CAAC"}
@@ -0,0 +1,44 @@
1
+ export const scrollbars = {
2
+ id: "styled-scrollbars",
3
+ title: "Styled scrollbars",
4
+ replaces: [
5
+ "react-custom-scrollbars",
6
+ "react-custom-scrollbars-2",
7
+ "simplebar",
8
+ "simplebar-react",
9
+ "overlayscrollbars",
10
+ "overlayscrollbars-react",
11
+ "perfect-scrollbar",
12
+ ],
13
+ featureIds: ["scrollbar-width", "scrollbar-color", "scrollbar-gutter"],
14
+ native: "scrollbar-width, scrollbar-color and scrollbar-gutter",
15
+ human: {
16
+ explainer: "Custom scrollbar libraries hide the real scrollbar and draw a fake one, which costs you native momentum scrolling, keyboard behaviour and accessibility. The standard properties restyle the actual scrollbar instead: scrollbar-width for thin or none, scrollbar-color for the thumb and track. scrollbar-gutter: stable is the one worth adding regardless, because it reserves the gutter and stops the page shifting sideways when content grows tall enough to need a scrollbar.",
17
+ snippet: `/* Reserve the gutter so the page does not jump. */
18
+ html {
19
+ scrollbar-gutter: stable;
20
+ }
21
+
22
+ .panel {
23
+ scrollbar-width: thin;
24
+ /* thumb, then track */
25
+ scrollbar-color: #666 transparent;
26
+ overflow-y: auto;
27
+ }`,
28
+ },
29
+ agent: {
30
+ when: "restyling a scrollbar to match a dark theme, or stopping layout shift when a scrollbar appears",
31
+ unless: [
32
+ "The design calls for a scrollbar shape the standard properties cannot express, such as a rounded floating thumb with a custom width in pixels. scrollbar-width only offers auto, thin and none.",
33
+ "You need the overlay-style scrollbar that appears on hover and takes no layout space on every platform.",
34
+ "You need identical scrollbars across operating systems for a design comp. Native scrollbars still look like the platform's.",
35
+ "You are relying on the library for scroll shadows or a virtualised list, which these properties do not address.",
36
+ ],
37
+ snippet: `html { scrollbar-gutter: stable; }
38
+ .panel {
39
+ scrollbar-width: thin;
40
+ scrollbar-color: #666 transparent;
41
+ }`,
42
+ },
43
+ };
44
+ //# sourceMappingURL=scrollbars.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scrollbars.js","sourceRoot":"","sources":["../../src/rules/scrollbars.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,UAAU,GAAS;IAC9B,EAAE,EAAE,mBAAmB;IACvB,KAAK,EAAE,mBAAmB;IAC1B,QAAQ,EAAE;QACR,yBAAyB;QACzB,2BAA2B;QAC3B,WAAW;QACX,iBAAiB;QACjB,mBAAmB;QACnB,yBAAyB;QACzB,mBAAmB;KACpB;IACD,UAAU,EAAE,CAAC,iBAAiB,EAAE,iBAAiB,EAAE,kBAAkB,CAAC;IACtE,MAAM,EAAE,uDAAuD;IAC/D,KAAK,EAAE;QACL,SAAS,EACP,wdAAwd;QAC1d,OAAO,EAAE;;;;;;;;;;EAUX;KACC;IACD,KAAK,EAAE;QACL,IAAI,EAAE,gGAAgG;QACtG,MAAM,EAAE;YACN,iMAAiM;YACjM,yGAAyG;YACzG,6HAA6H;YAC7H,iHAAiH;SAClH;QACD,OAAO,EAAE;;;;EAIX;KACC;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Rule } from "../schema.ts";
2
+ export declare const select: Rule;
3
+ //# sourceMappingURL=select.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../src/rules/select.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,MAAM,EAAE,IAqDpB,CAAC"}
@@ -0,0 +1,54 @@
1
+ export const select = {
2
+ id: "customizable-select",
3
+ title: "Custom select menus",
4
+ replaces: ["react-select", "choices.js", "select2", "tom-select"],
5
+ featureIds: ["customizable-select"],
6
+ native: "appearance: base-select on <select>",
7
+ human: {
8
+ explainer: "Opting a select into appearance: base-select makes its picker a normal, styleable part of the page, so options can hold markup: an avatar, a swatch, a second line of muted text. The keyboard behaviour, the accessible role and the mobile picker stay the browser's, which is the part custom select components most often get wrong. This covers presentation. It does not turn a select into a combobox.",
9
+ snippet: `<select>
10
+ <button>
11
+ <selectedcontent></selectedcontent>
12
+ </button>
13
+ <option value="de">
14
+ <span aria-hidden="true">DE</span> Germany
15
+ </option>
16
+ <option value="at">
17
+ <span aria-hidden="true">AT</span> Austria
18
+ </option>
19
+ </select>
20
+
21
+ <style>
22
+ select,
23
+ select::picker(select) {
24
+ appearance: base-select;
25
+ }
26
+
27
+ select::picker(select) {
28
+ border-radius: 0.5rem;
29
+ padding: 0.25rem;
30
+ }
31
+
32
+ option:checked {
33
+ font-weight: 600;
34
+ }
35
+ </style>`,
36
+ },
37
+ agent: {
38
+ when: "styling a select's options with markup, such as a flag or a two-line label",
39
+ unless: [
40
+ "You need typeahead filtering, multi-select with tags, or options loaded asynchronously from a search. Those make it a combobox, and a select is the wrong element regardless of styling.",
41
+ "You need creatable options, where the user can add a value that is not in the list.",
42
+ "You need anything beyond Chromium today. Customizable select is limited availability. It degrades to a normal select, which is a safe fallback, but the design will not match.",
43
+ "You need grouped options with sticky group headers while scrolling.",
44
+ ],
45
+ snippet: `<select>
46
+ <button><selectedcontent></selectedcontent></button>
47
+ <option value="a"><span>A</span> Option A</option>
48
+ </select>
49
+ <style>
50
+ select, select::picker(select) { appearance: base-select; }
51
+ </style>`,
52
+ },
53
+ };
54
+ //# sourceMappingURL=select.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select.js","sourceRoot":"","sources":["../../src/rules/select.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,MAAM,GAAS;IAC1B,EAAE,EAAE,qBAAqB;IACzB,KAAK,EAAE,qBAAqB;IAC5B,QAAQ,EAAE,CAAC,cAAc,EAAE,YAAY,EAAE,SAAS,EAAE,YAAY,CAAC;IACjE,UAAU,EAAE,CAAC,qBAAqB,CAAC;IACnC,MAAM,EAAE,qCAAqC;IAC7C,KAAK,EAAE;QACL,SAAS,EACP,+YAA+Y;QACjZ,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;SA0BJ;KACN;IACD,KAAK,EAAE;QACL,IAAI,EAAE,4EAA4E;QAClF,MAAM,EAAE;YACN,0LAA0L;YAC1L,qFAAqF;YACrF,gLAAgL;YAChL,qEAAqE;SACtE;QACD,OAAO,EAAE;;;;;;SAMJ;KACN;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Rule } from "../schema.ts";
2
+ export declare const smoothScroll: Rule;
3
+ //# sourceMappingURL=smooth-scroll.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"smooth-scroll.d.ts","sourceRoot":"","sources":["../../src/rules/smooth-scroll.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,YAAY,EAAE,IAwC1B,CAAC"}
@@ -0,0 +1,41 @@
1
+ export const smoothScroll = {
2
+ id: "smooth-scroll",
3
+ title: "Smooth scrolling and scroll-to-anchor",
4
+ replaces: [
5
+ "react-scroll",
6
+ "smoothscroll-polyfill",
7
+ "scroll-behavior-polyfill",
8
+ "smooth-scroll",
9
+ "jump.js",
10
+ ],
11
+ featureIds: ["scroll-behavior"],
12
+ native: "scroll-behavior: smooth with scroll-margin-top",
13
+ human: {
14
+ explainer: "One CSS declaration makes every in-page anchor and every scrollIntoView call animate instead of jump. The piece people miss is scroll-margin-top, which stops a sticky header from covering the heading you just scrolled to, and it works for both anchor links and focus. Gate the whole thing behind prefers-reduced-motion, because a long smooth scroll is a common motion-sickness trigger.",
15
+ snippet: `@media (prefers-reduced-motion: no-preference) {
16
+ :root {
17
+ scroll-behavior: smooth;
18
+ }
19
+ }
20
+
21
+ /* Stop a sticky header covering the target. */
22
+ :target,
23
+ [id] {
24
+ scroll-margin-top: 5rem;
25
+ }`,
26
+ },
27
+ agent: {
28
+ when: "making in-page anchor links scroll smoothly to their target",
29
+ unless: [
30
+ "You need to control the duration or easing of the scroll. CSS gives you no handle on either, and browsers differ.",
31
+ "You need a callback when the scroll finishes. scrollend helps, but it is newer than scroll-behavior itself.",
32
+ "You need to scroll to a coordinate that is computed rather than to an element.",
33
+ "You need scroll spy, meaning highlighting the nav item for the section currently in view. That is a separate problem and still needs JavaScript or scroll-driven animations.",
34
+ ],
35
+ snippet: `@media (prefers-reduced-motion: no-preference) {
36
+ :root { scroll-behavior: smooth; }
37
+ }
38
+ [id] { scroll-margin-top: 5rem; }`,
39
+ },
40
+ };
41
+ //# sourceMappingURL=smooth-scroll.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"smooth-scroll.js","sourceRoot":"","sources":["../../src/rules/smooth-scroll.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,YAAY,GAAS;IAChC,EAAE,EAAE,eAAe;IACnB,KAAK,EAAE,uCAAuC;IAC9C,QAAQ,EAAE;QACR,cAAc;QACd,uBAAuB;QACvB,0BAA0B;QAC1B,eAAe;QACf,SAAS;KACV;IACD,UAAU,EAAE,CAAC,iBAAiB,CAAC;IAC/B,MAAM,EAAE,gDAAgD;IACxD,KAAK,EAAE;QACL,SAAS,EACP,mYAAmY;QACrY,OAAO,EAAE;;;;;;;;;;EAUX;KACC;IACD,KAAK,EAAE;QACL,IAAI,EAAE,6DAA6D;QACnE,MAAM,EAAE;YACN,mHAAmH;YACnH,6GAA6G;YAC7G,gFAAgF;YAChF,8KAA8K;SAC/K;QACD,OAAO,EAAE;;;kCAGqB;KAC/B;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Rule } from "../schema.ts";
2
+ export declare const sticky: Rule;
3
+ //# sourceMappingURL=sticky.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sticky.d.ts","sourceRoot":"","sources":["../../src/rules/sticky.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,MAAM,EAAE,IAsCpB,CAAC"}
@@ -0,0 +1,39 @@
1
+ export const sticky = {
2
+ id: "sticky-positioning",
3
+ title: "Sticky headers and sidebars",
4
+ replaces: [
5
+ "sticky-js",
6
+ "stickyfill",
7
+ "react-sticky",
8
+ "sticky-kit",
9
+ "stickybits",
10
+ ],
11
+ featureIds: ["sticky-positioning"],
12
+ native: "position: sticky",
13
+ human: {
14
+ explainer: "These libraries measured scroll position and toggled position: fixed with a computed offset. position: sticky does it in the compositor, so it does not jitter and does not run code on scroll. Two things trip people up: sticky is relative to the nearest scrolling ancestor, so an overflow: hidden or overflow: auto anywhere up the tree silently breaks it, and you must set at least one of top, right, bottom or left.",
15
+ snippet: `.site-header {
16
+ position: sticky;
17
+ top: 0;
18
+ z-index: 10;
19
+ }
20
+
21
+ /* A sidebar that sticks until its section scrolls past. */
22
+ .sidebar {
23
+ position: sticky;
24
+ top: 5rem;
25
+ align-self: start;
26
+ }`,
27
+ },
28
+ agent: {
29
+ when: "a header, sidebar or table head should stick while its container scrolls",
30
+ unless: [
31
+ "You need to know when the element became stuck, to add a shadow or shrink it. Nothing in CSS exposes that state directly, so this still wants an IntersectionObserver sentinel.",
32
+ "You need the element to stick relative to the viewport while its parent has overflow set. Sticky is scoped to the nearest scroll container, so this needs a different structure.",
33
+ "You need it to stop sticking at a computed point unrelated to its containing block.",
34
+ ],
35
+ snippet: `.header { position: sticky; top: 0; z-index: 10; }
36
+ .sidebar { position: sticky; top: 5rem; align-self: start; }`,
37
+ },
38
+ };
39
+ //# sourceMappingURL=sticky.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sticky.js","sourceRoot":"","sources":["../../src/rules/sticky.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,MAAM,GAAS;IAC1B,EAAE,EAAE,oBAAoB;IACxB,KAAK,EAAE,6BAA6B;IACpC,QAAQ,EAAE;QACR,WAAW;QACX,YAAY;QACZ,cAAc;QACd,YAAY;QACZ,YAAY;KACb;IACD,UAAU,EAAE,CAAC,oBAAoB,CAAC;IAClC,MAAM,EAAE,kBAAkB;IAC1B,KAAK,EAAE;QACL,SAAS,EACP,iaAAia;QACna,OAAO,EAAE;;;;;;;;;;;EAWX;KACC;IACD,KAAK,EAAE;QACL,IAAI,EAAE,0EAA0E;QAChF,MAAM,EAAE;YACN,iLAAiL;YACjL,kLAAkL;YAClL,qFAAqF;SACtF;QACD,OAAO,EAAE;6DACgD;KAC1D;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Rule } from "../schema.ts";
2
+ export declare const textBoxTrim: Rule;
3
+ //# sourceMappingURL=text-box-trim.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-box-trim.d.ts","sourceRoot":"","sources":["../../src/rules/text-box-trim.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,WAAW,EAAE,IA+BzB,CAAC"}
@@ -0,0 +1,32 @@
1
+ export const textBoxTrim = {
2
+ id: "text-box-trim",
3
+ title: "Trimming font leading",
4
+ replaces: ["capsize", "@capsizecss/core", "@capsizecss/metrics"],
5
+ featureIds: ["text-box"],
6
+ native: "text-box-trim and text-box-edge",
7
+ human: {
8
+ explainer: "Every font ships with space above the cap height and below the baseline, so a heading never sits flush against the box you gave it, and optical alignment ends up as hand-tuned negative margins. Capsize computes those metrics and generates the margins for you. text-box-trim asks the browser to remove that space directly, using metrics it already has, so a button label centres properly and a heading's spacing matches what the design specified.",
9
+ snippet: `h1,
10
+ .button {
11
+ /* Trim the leading above the cap height and
12
+ below the baseline. */
13
+ text-box: trim-both cap alphabetic;
14
+ }
15
+
16
+ /* Longhand form. */
17
+ .label {
18
+ text-box-trim: trim-both;
19
+ text-box-edge: cap alphabetic;
20
+ }`,
21
+ },
22
+ agent: {
23
+ when: "removing a font's built-in leading so text sits flush in its box",
24
+ unless: [
25
+ "You are shipping to production outside Chromium. text-box is limited availability, and the fallback is the untrimmed spacing you started with, which shifts your vertical rhythm between browsers.",
26
+ "You need the computed metrics as numbers at build time, for example to generate spacing tokens or to lay out text in a canvas or a PDF. Capsize gives you values; CSS only affects rendering.",
27
+ "You need to support a font whose metrics are wrong or missing, which Capsize lets you override by hand.",
28
+ ],
29
+ snippet: "h1 { text-box: trim-both cap alphabetic; }",
30
+ },
31
+ };
32
+ //# sourceMappingURL=text-box-trim.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-box-trim.js","sourceRoot":"","sources":["../../src/rules/text-box-trim.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,WAAW,GAAS;IAC/B,EAAE,EAAE,eAAe;IACnB,KAAK,EAAE,uBAAuB;IAC9B,QAAQ,EAAE,CAAC,SAAS,EAAE,kBAAkB,EAAE,qBAAqB,CAAC;IAChE,UAAU,EAAE,CAAC,UAAU,CAAC;IACxB,MAAM,EAAE,iCAAiC;IACzC,KAAK,EAAE;QACL,SAAS,EACP,+bAA+b;QACjc,OAAO,EAAE;;;;;;;;;;;EAWX;KACC;IACD,KAAK,EAAE;QACL,IAAI,EAAE,kEAAkE;QACxE,MAAM,EAAE;YACN,oMAAoM;YACpM,+LAA+L;YAC/L,yGAAyG;SAC1G;QACD,OAAO,EAAE,4CAA4C;KACtD;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Rule } from "../schema.ts";
2
+ export declare const textWrapBalance: Rule;
3
+ //# sourceMappingURL=text-wrap-balance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-wrap-balance.d.ts","sourceRoot":"","sources":["../../src/rules/text-wrap-balance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,eAAe,EAAE,IAiC7B,CAAC"}
@@ -0,0 +1,34 @@
1
+ export const textWrapBalance = {
2
+ id: "text-wrap-balance",
3
+ title: "Balanced headings",
4
+ replaces: ["react-wrap-balancer", "balance-text"],
5
+ featureIds: ["text-wrap-balance"],
6
+ native: "text-wrap: balance",
7
+ human: {
8
+ explainer: "A balancer measures the text, then re-flows it so the last line is not a single orphaned word. text-wrap: balance asks the browser to do the same thing during layout, with no measuring pass and no layout shift after hydration. Browsers cap the line count they will balance, usually around four to six, so it is aimed at headings and short blurbs rather than paragraphs. For body copy, text-wrap: pretty handles orphans without the cap.",
9
+ snippet: `h1,
10
+ h2,
11
+ h3,
12
+ blockquote {
13
+ text-wrap: balance;
14
+ }
15
+
16
+ /* For longer copy, avoid a single-word last line
17
+ without balancing the whole block. */
18
+ p {
19
+ text-wrap: pretty;
20
+ }`,
21
+ },
22
+ agent: {
23
+ when: "stopping a heading or short blurb from breaking with one word on the last line",
24
+ unless: [
25
+ "The text runs longer than about four lines. Browsers stop balancing past a line-count cap, so long paragraphs are unaffected. Use text-wrap: pretty there.",
26
+ "You need identical line breaks across every browser, for example to match a design comp pixel for pixel. Balancing is a browser heuristic and the results differ.",
27
+ "You need to balance to a specific ratio or set a maximum line width in characters, which the library exposes and CSS does not.",
28
+ "You are counting on text-wrap: pretty as the fallback for body copy. It has much narrower support than balance, so treat it as an enhancement.",
29
+ ],
30
+ snippet: `h1, h2, h3 { text-wrap: balance; }
31
+ p { text-wrap: pretty; }`,
32
+ },
33
+ };
34
+ //# sourceMappingURL=text-wrap-balance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-wrap-balance.js","sourceRoot":"","sources":["../../src/rules/text-wrap-balance.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,eAAe,GAAS;IACnC,EAAE,EAAE,mBAAmB;IACvB,KAAK,EAAE,mBAAmB;IAC1B,QAAQ,EAAE,CAAC,qBAAqB,EAAE,cAAc,CAAC;IACjD,UAAU,EAAE,CAAC,mBAAmB,CAAC;IACjC,MAAM,EAAE,oBAAoB;IAC5B,KAAK,EAAE;QACL,SAAS,EACP,qbAAqb;QACvb,OAAO,EAAE;;;;;;;;;;;EAWX;KACC;IACD,KAAK,EAAE;QACL,IAAI,EAAE,gFAAgF;QACtF,MAAM,EAAE;YACN,4JAA4J;YAC5J,mKAAmK;YACnK,gIAAgI;YAChI,gJAAgJ;SACjJ;QACD,OAAO,EAAE;yBACY;KACtB;CACF,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Rule } from "../schema.ts";
2
+ export declare const viewTransitions: Rule;
3
+ //# sourceMappingURL=view-transitions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"view-transitions.d.ts","sourceRoot":"","sources":["../../src/rules/view-transitions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,eAAe,EAAE,IAoD7B,CAAC"}