@jomae/catalog 0.7.0 → 0.10.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/baseline.d.ts +41 -2
- package/dist/baseline.d.ts.map +1 -1
- package/dist/baseline.js +52 -10
- package/dist/baseline.js.map +1 -1
- package/dist/detect.d.ts +26 -0
- package/dist/detect.d.ts.map +1 -1
- package/dist/detect.js +27 -1
- package/dist/detect.js.map +1 -1
- package/dist/generated/baseline-history.d.ts.map +1 -1
- package/dist/generated/baseline-history.js +17 -5
- package/dist/generated/baseline-history.js.map +1 -1
- package/dist/generated/baseline.d.ts.map +1 -1
- package/dist/generated/baseline.js +411 -35
- package/dist/generated/baseline.js.map +1 -1
- package/dist/generated/guides.d.ts.map +1 -1
- package/dist/generated/guides.js +26 -3
- package/dist/generated/guides.js.map +1 -1
- package/dist/generated/lint-rules.d.ts +26 -0
- package/dist/generated/lint-rules.d.ts.map +1 -0
- package/dist/generated/lint-rules.js +361 -0
- package/dist/generated/lint-rules.js.map +1 -0
- package/dist/generated/sizes.d.ts.map +1 -1
- package/dist/generated/sizes.js +408 -38
- package/dist/generated/sizes.js.map +1 -1
- package/dist/generated/support-claims.d.ts.map +1 -1
- package/dist/generated/support-claims.js +34 -3
- package/dist/generated/support-claims.js.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/lint.d.ts +53 -0
- package/dist/lint.d.ts.map +1 -0
- package/dist/lint.js +41 -0
- package/dist/lint.js.map +1 -0
- package/dist/markdown.d.ts +7 -0
- package/dist/markdown.d.ts.map +1 -1
- package/dist/markdown.js +81 -2
- package/dist/markdown.js.map +1 -1
- package/dist/rules/abort-controller.d.ts.map +1 -1
- package/dist/rules/abort-controller.js +3 -0
- package/dist/rules/abort-controller.js.map +1 -1
- package/dist/rules/accordion.d.ts.map +1 -1
- package/dist/rules/accordion.js +3 -0
- package/dist/rules/accordion.js.map +1 -1
- package/dist/rules/array-grouping.d.ts.map +1 -1
- package/dist/rules/array-grouping.js +1 -0
- package/dist/rules/array-grouping.js.map +1 -1
- package/dist/rules/aspect-ratio.d.ts.map +1 -1
- package/dist/rules/aspect-ratio.js +4 -0
- package/dist/rules/aspect-ratio.js.map +1 -1
- package/dist/rules/base64.d.ts.map +1 -1
- package/dist/rules/base64.js +3 -0
- package/dist/rules/base64.js.map +1 -1
- package/dist/rules/broadcast-channel.d.ts.map +1 -1
- package/dist/rules/broadcast-channel.js +3 -0
- package/dist/rules/broadcast-channel.js.map +1 -1
- package/dist/rules/carousel.d.ts.map +1 -1
- package/dist/rules/carousel.js +5 -0
- package/dist/rules/carousel.js.map +1 -1
- package/dist/rules/clipboard.d.ts.map +1 -1
- package/dist/rules/clipboard.js +3 -0
- package/dist/rules/clipboard.js.map +1 -1
- package/dist/rules/color-functions.d.ts.map +1 -1
- package/dist/rules/color-functions.js +4 -0
- package/dist/rules/color-functions.js.map +1 -1
- package/dist/rules/container-queries.d.ts.map +1 -1
- package/dist/rules/container-queries.js +4 -0
- package/dist/rules/container-queries.js.map +1 -1
- package/dist/rules/cookie-store.d.ts +3 -0
- package/dist/rules/cookie-store.d.ts.map +1 -0
- package/dist/rules/cookie-store.js +38 -0
- package/dist/rules/cookie-store.js.map +1 -0
- package/dist/rules/css-has.d.ts +3 -0
- package/dist/rules/css-has.d.ts.map +1 -0
- package/dist/rules/css-has.js +35 -0
- package/dist/rules/css-has.js.map +1 -0
- package/dist/rules/css-nesting.d.ts +3 -0
- package/dist/rules/css-nesting.d.ts.map +1 -0
- package/dist/rules/css-nesting.js +35 -0
- package/dist/rules/css-nesting.js.map +1 -0
- package/dist/rules/date-format.d.ts +3 -0
- package/dist/rules/date-format.d.ts.map +1 -0
- package/dist/rules/date-format.js +33 -0
- package/dist/rules/date-format.js.map +1 -0
- package/dist/rules/date-time-input.d.ts.map +1 -1
- package/dist/rules/date-time-input.js +4 -0
- package/dist/rules/date-time-input.js.map +1 -1
- package/dist/rules/diacritics.d.ts +3 -0
- package/dist/rules/diacritics.d.ts.map +1 -0
- package/dist/rules/diacritics.js +34 -0
- package/dist/rules/diacritics.js.map +1 -0
- package/dist/rules/dialog.d.ts.map +1 -1
- package/dist/rules/dialog.js +4 -0
- package/dist/rules/dialog.js.map +1 -1
- package/dist/rules/discrete-transitions.d.ts.map +1 -1
- package/dist/rules/discrete-transitions.js +4 -0
- package/dist/rules/discrete-transitions.js.map +1 -1
- package/dist/rules/display-names.d.ts +3 -0
- package/dist/rules/display-names.d.ts.map +1 -0
- package/dist/rules/display-names.js +37 -0
- package/dist/rules/display-names.js.map +1 -0
- package/dist/rules/drag-and-drop.d.ts.map +1 -1
- package/dist/rules/drag-and-drop.js +4 -0
- package/dist/rules/drag-and-drop.js.map +1 -1
- package/dist/rules/duration-format.d.ts.map +1 -1
- package/dist/rules/duration-format.js +3 -0
- package/dist/rules/duration-format.js.map +1 -1
- package/dist/rules/event-target.d.ts.map +1 -1
- package/dist/rules/event-target.js +1 -0
- package/dist/rules/event-target.js.map +1 -1
- package/dist/rules/fetch.d.ts.map +1 -1
- package/dist/rules/fetch.js +4 -0
- package/dist/rules/fetch.js.map +1 -1
- package/dist/rules/field-sizing.d.ts.map +1 -1
- package/dist/rules/field-sizing.js +4 -0
- package/dist/rules/field-sizing.js.map +1 -1
- package/dist/rules/file-download.d.ts +3 -0
- package/dist/rules/file-download.d.ts.map +1 -0
- package/dist/rules/file-download.js +40 -0
- package/dist/rules/file-download.js.map +1 -0
- package/dist/rules/file-drop.d.ts +3 -0
- package/dist/rules/file-drop.d.ts.map +1 -0
- package/dist/rules/file-drop.js +40 -0
- package/dist/rules/file-drop.js.map +1 -0
- package/dist/rules/focus-visible.d.ts.map +1 -1
- package/dist/rules/focus-visible.js +4 -0
- package/dist/rules/focus-visible.js.map +1 -1
- package/dist/rules/font-loading.d.ts +3 -0
- package/dist/rules/font-loading.d.ts.map +1 -0
- package/dist/rules/font-loading.js +33 -0
- package/dist/rules/font-loading.js.map +1 -0
- package/dist/rules/form-validation.d.ts +3 -0
- package/dist/rules/form-validation.d.ts.map +1 -0
- package/dist/rules/form-validation.js +40 -0
- package/dist/rules/form-validation.js.map +1 -0
- package/dist/rules/fullscreen.d.ts.map +1 -1
- package/dist/rules/fullscreen.js +3 -0
- package/dist/rules/fullscreen.js.map +1 -1
- package/dist/rules/height-animation.d.ts.map +1 -1
- package/dist/rules/height-animation.js +4 -0
- package/dist/rules/height-animation.js.map +1 -1
- package/dist/rules/index.d.ts.map +1 -1
- package/dist/rules/index.js +50 -0
- package/dist/rules/index.js.map +1 -1
- package/dist/rules/inert.d.ts.map +1 -1
- package/dist/rules/inert.js +6 -0
- package/dist/rules/inert.js.map +1 -1
- package/dist/rules/intersection-observer.d.ts.map +1 -1
- package/dist/rules/intersection-observer.js +1 -0
- package/dist/rules/intersection-observer.js.map +1 -1
- package/dist/rules/jquery.d.ts +3 -0
- package/dist/rules/jquery.d.ts.map +1 -0
- package/dist/rules/jquery.js +37 -0
- package/dist/rules/jquery.js.map +1 -0
- package/dist/rules/lazy-loading.d.ts.map +1 -1
- package/dist/rules/lazy-loading.js +4 -0
- package/dist/rules/lazy-loading.js.map +1 -1
- package/dist/rules/light-dark.d.ts +3 -0
- package/dist/rules/light-dark.d.ts.map +1 -0
- package/dist/rules/light-dark.js +37 -0
- package/dist/rules/light-dark.js.map +1 -0
- package/dist/rules/line-clamp.d.ts.map +1 -1
- package/dist/rules/line-clamp.js +4 -0
- package/dist/rules/line-clamp.js.map +1 -1
- package/dist/rules/list-format.d.ts +3 -0
- package/dist/rules/list-format.d.ts.map +1 -0
- package/dist/rules/list-format.js +40 -0
- package/dist/rules/list-format.js.map +1 -0
- package/dist/rules/masonry.d.ts.map +1 -1
- package/dist/rules/masonry.js +4 -0
- package/dist/rules/masonry.js.map +1 -1
- package/dist/rules/match-media.d.ts +3 -0
- package/dist/rules/match-media.d.ts.map +1 -0
- package/dist/rules/match-media.js +36 -0
- package/dist/rules/match-media.js.map +1 -0
- package/dist/rules/natural-sort.d.ts.map +1 -1
- package/dist/rules/natural-sort.js +4 -0
- package/dist/rules/natural-sort.js.map +1 -1
- package/dist/rules/number-format.d.ts.map +1 -1
- package/dist/rules/number-format.js +14 -1
- package/dist/rules/number-format.js.map +1 -1
- package/dist/rules/page-visibility.d.ts.map +1 -1
- package/dist/rules/page-visibility.js +3 -0
- package/dist/rules/page-visibility.js.map +1 -1
- package/dist/rules/passkeys.d.ts +3 -0
- package/dist/rules/passkeys.d.ts.map +1 -0
- package/dist/rules/passkeys.js +44 -0
- package/dist/rules/passkeys.js.map +1 -0
- package/dist/rules/plural-rules.d.ts +3 -0
- package/dist/rules/plural-rules.d.ts.map +1 -0
- package/dist/rules/plural-rules.js +33 -0
- package/dist/rules/plural-rules.js.map +1 -0
- package/dist/rules/pointer-events.d.ts +3 -0
- package/dist/rules/pointer-events.d.ts.map +1 -0
- package/dist/rules/pointer-events.js +43 -0
- package/dist/rules/pointer-events.js.map +1 -0
- package/dist/rules/popover.d.ts.map +1 -1
- package/dist/rules/popover.js +5 -0
- package/dist/rules/popover.js.map +1 -1
- package/dist/rules/progress-indicator.d.ts +3 -0
- package/dist/rules/progress-indicator.d.ts.map +1 -0
- package/dist/rules/progress-indicator.js +39 -0
- package/dist/rules/progress-indicator.js.map +1 -0
- package/dist/rules/random-uuid.d.ts.map +1 -1
- package/dist/rules/random-uuid.js +4 -0
- package/dist/rules/random-uuid.js.map +1 -1
- package/dist/rules/relative-time.d.ts.map +1 -1
- package/dist/rules/relative-time.js +4 -0
- package/dist/rules/relative-time.js.map +1 -1
- package/dist/rules/resizable-panels.d.ts.map +1 -1
- package/dist/rules/resizable-panels.js +3 -0
- package/dist/rules/resizable-panels.js.map +1 -1
- package/dist/rules/resize-observer.d.ts.map +1 -1
- package/dist/rules/resize-observer.js +4 -0
- package/dist/rules/resize-observer.js.map +1 -1
- package/dist/rules/screen-wake-lock.d.ts.map +1 -1
- package/dist/rules/screen-wake-lock.js +4 -0
- package/dist/rules/screen-wake-lock.js.map +1 -1
- package/dist/rules/scroll-animations.d.ts.map +1 -1
- package/dist/rules/scroll-animations.js +4 -0
- package/dist/rules/scroll-animations.js.map +1 -1
- package/dist/rules/scroll-into-view.d.ts +3 -0
- package/dist/rules/scroll-into-view.d.ts.map +1 -0
- package/dist/rules/scroll-into-view.js +38 -0
- package/dist/rules/scroll-into-view.js.map +1 -0
- package/dist/rules/scroll-lock.d.ts.map +1 -1
- package/dist/rules/scroll-lock.js +3 -0
- package/dist/rules/scroll-lock.js.map +1 -1
- package/dist/rules/scrollbars.d.ts.map +1 -1
- package/dist/rules/scrollbars.js +3 -0
- package/dist/rules/scrollbars.js.map +1 -1
- package/dist/rules/segmenter.d.ts +3 -0
- package/dist/rules/segmenter.d.ts.map +1 -0
- package/dist/rules/segmenter.js +45 -0
- package/dist/rules/segmenter.js.map +1 -0
- package/dist/rules/select.d.ts.map +1 -1
- package/dist/rules/select.js +4 -0
- package/dist/rules/select.js.map +1 -1
- package/dist/rules/server-sent-events.d.ts.map +1 -1
- package/dist/rules/server-sent-events.js +4 -0
- package/dist/rules/server-sent-events.js.map +1 -1
- package/dist/rules/signal-timeout.d.ts +3 -0
- package/dist/rules/signal-timeout.d.ts.map +1 -0
- package/dist/rules/signal-timeout.js +31 -0
- package/dist/rules/signal-timeout.js.map +1 -0
- package/dist/rules/smooth-scroll.d.ts.map +1 -1
- package/dist/rules/smooth-scroll.js +4 -0
- package/dist/rules/smooth-scroll.js.map +1 -1
- package/dist/rules/speculation-rules.d.ts +3 -0
- package/dist/rules/speculation-rules.d.ts.map +1 -0
- package/dist/rules/speculation-rules.js +35 -0
- package/dist/rules/speculation-rules.js.map +1 -0
- package/dist/rules/sticky.d.ts.map +1 -1
- package/dist/rules/sticky.js +4 -0
- package/dist/rules/sticky.js.map +1 -1
- package/dist/rules/structured-clone.d.ts.map +1 -1
- package/dist/rules/structured-clone.js +1 -0
- package/dist/rules/structured-clone.js.map +1 -1
- package/dist/rules/temporal.d.ts +3 -0
- package/dist/rules/temporal.d.ts.map +1 -0
- package/dist/rules/temporal.js +34 -0
- package/dist/rules/temporal.js.map +1 -0
- package/dist/rules/text-wrap-balance.d.ts.map +1 -1
- package/dist/rules/text-wrap-balance.js +3 -0
- package/dist/rules/text-wrap-balance.js.map +1 -1
- package/dist/rules/url-pattern.d.ts +3 -0
- package/dist/rules/url-pattern.d.ts.map +1 -0
- package/dist/rules/url-pattern.js +40 -0
- package/dist/rules/url-pattern.js.map +1 -0
- package/dist/rules/url-search-params.d.ts.map +1 -1
- package/dist/rules/url-search-params.js +1 -0
- package/dist/rules/url-search-params.js.map +1 -1
- package/dist/rules/web-animations.d.ts +3 -0
- package/dist/rules/web-animations.d.ts.map +1 -0
- package/dist/rules/web-animations.js +44 -0
- package/dist/rules/web-animations.js.map +1 -0
- package/dist/rules/web-crypto.d.ts.map +1 -1
- package/dist/rules/web-crypto.js +4 -0
- package/dist/rules/web-crypto.js.map +1 -1
- package/dist/rules/web-locks.d.ts +3 -0
- package/dist/rules/web-locks.d.ts.map +1 -0
- package/dist/rules/web-locks.js +39 -0
- package/dist/rules/web-locks.js.map +1 -0
- package/dist/rules/web-share.d.ts.map +1 -1
- package/dist/rules/web-share.js +3 -0
- package/dist/rules/web-share.js.map +1 -1
- package/dist/rules/with-resolvers.d.ts +3 -0
- package/dist/rules/with-resolvers.d.ts.map +1 -0
- package/dist/rules/with-resolvers.js +30 -0
- package/dist/rules/with-resolvers.js.map +1 -0
- package/dist/schema.d.ts +4 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +34 -0
- package/dist/schema.js.map +1 -1
- package/dist/tier-diff.d.ts +55 -0
- package/dist/tier-diff.d.ts.map +1 -0
- package/dist/tier-diff.js +61 -0
- package/dist/tier-diff.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export const jquery = {
|
|
2
|
+
id: "jquery",
|
|
3
|
+
title: "jQuery",
|
|
4
|
+
category: "async-data",
|
|
5
|
+
replaces: ["jquery"],
|
|
6
|
+
featureIds: ["dom", "events", "web-animations"],
|
|
7
|
+
native: "querySelectorAll(), classList and addEventListener()",
|
|
8
|
+
human: {
|
|
9
|
+
explainer: "jQuery smoothed over a decade of disagreement between browsers about selectors, events, animation and XMLHttpRequest. Each of those became one standard method that works everywhere: querySelectorAll for finding, classList for classes, closest for walking up, addEventListener for events, animate for motion and fetch for requests. What is left of the library is the chaining syntax and the plugin ecosystem built on top of it.",
|
|
10
|
+
snippet: `// $(".item").addClass("on") becomes:
|
|
11
|
+
for (const el of document.querySelectorAll(".item")) {
|
|
12
|
+
el.classList.add("on");
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// $(el).closest("form") becomes:
|
|
16
|
+
el.closest("form");
|
|
17
|
+
|
|
18
|
+
// $(el).fadeIn() becomes:
|
|
19
|
+
el.animate({ opacity: [0, 1] }, { duration: 200, fill: "forwards" });`,
|
|
20
|
+
mdnUrl: "https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll",
|
|
21
|
+
},
|
|
22
|
+
agent: {
|
|
23
|
+
when: "jQuery is used for selectors, class and attribute changes, events or simple animation",
|
|
24
|
+
unless: [
|
|
25
|
+
"Plugins are installed that require the global. Bootstrap 4, Select2, slick and DataTables all expect $ to exist, so the library stays until each of those goes, and that is usually the whole job rather than a step in it.",
|
|
26
|
+
"You depend on $.ajax behaviour with no fetch equivalent, JSONP most of all. fetch cannot do JSONP at all, and upload progress still needs XMLHttpRequest.",
|
|
27
|
+
"Event delegation and namespacing are used heavily. Delegation is a target.closest check inside one listener, which is fine once and tedious across a large codebase, and namespaced off() has no direct counterpart.",
|
|
28
|
+
"jQuery is loaded from a CDN that is already cached, or it arrives through a server-rendered template you do not control. Removing the import does not remove the request in either case.",
|
|
29
|
+
"The codebase leans on jQuery's quirks, such as its own event object, its data() store, or :visible and other selectors that are not valid CSS and that querySelectorAll will reject.",
|
|
30
|
+
],
|
|
31
|
+
snippet: 'for (const el of document.querySelectorAll(".item")) el.classList.add("on");',
|
|
32
|
+
handRolled: [
|
|
33
|
+
"a $ or qs helper wrapping querySelectorAll to get chaining back after the library was removed",
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=jquery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jquery.js","sourceRoot":"","sources":["../../src/rules/jquery.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,MAAM,GAAS;IAC1B,EAAE,EAAE,QAAQ;IACZ,KAAK,EAAE,QAAQ;IACf,QAAQ,EAAE,YAAY;IACtB,QAAQ,EAAE,CAAC,QAAQ,CAAC;IACpB,UAAU,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,gBAAgB,CAAC;IAC/C,MAAM,EAAE,sDAAsD;IAC9D,KAAK,EAAE;QACL,SAAS,EACP,4aAA4a;QAC9a,OAAO,EAAE;;;;;;;;;sEASyD;QAClE,MAAM,EACJ,4EAA4E;KAC/E;IACD,KAAK,EAAE;QACL,IAAI,EAAE,uFAAuF;QAC7F,MAAM,EAAE;YACN,6NAA6N;YAC7N,2JAA2J;YAC3J,sNAAsN;YACtN,0LAA0L;YAC1L,sLAAsL;SACvL;QACD,OAAO,EACL,8EAA8E;QAChF,UAAU,EAAE;YACV,+FAA+F;SAChG;KACF;CACF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lazy-loading.d.ts","sourceRoot":"","sources":["../../src/rules/lazy-loading.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"lazy-loading.d.ts","sourceRoot":"","sources":["../../src/rules/lazy-loading.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,WAAW,EAAE,IAyCzB,CAAC"}
|
|
@@ -31,6 +31,10 @@ export const lazyLoading = {
|
|
|
31
31
|
],
|
|
32
32
|
snippet: `<img src="/photo.jpg" alt="" loading="lazy" />
|
|
33
33
|
<iframe src="/embed" loading="lazy"></iframe>`,
|
|
34
|
+
handRolled: [
|
|
35
|
+
"an IntersectionObserver that swaps a data-src attribute into src when an image nears the viewport",
|
|
36
|
+
"a scroll listener deciding which images are close enough to start loading",
|
|
37
|
+
],
|
|
34
38
|
},
|
|
35
39
|
guides: ["optimize-image-priority"],
|
|
36
40
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lazy-loading.js","sourceRoot":"","sources":["../../src/rules/lazy-loading.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,WAAW,GAAS;IAC/B,EAAE,EAAE,cAAc;IAClB,KAAK,EAAE,gCAAgC;IACvC,QAAQ,EAAE,YAAY;IACtB,QAAQ,EAAE;QACR,OAAO;QACP,WAAW;QACX,kBAAkB;QAClB,gBAAgB;QAChB,iCAAiC;QACjC,SAAS;QACT,cAAc;QACd,cAAc;KACf;IACD,UAAU,EAAE,CAAC,cAAc,CAAC;IAC5B,MAAM,EAAE,gBAAgB;IACxB,KAAK,EAAE;QACL,SAAS,EACP,4XAA4X;QAC9X,OAAO,EAAE;iEACoD;QAC7D,MAAM,EACJ,uEAAuE;KAC1E;IACD,KAAK,EAAE;QACL,IAAI,EAAE,gFAAgF;QACtF,MAAM,EAAE;YACN,gJAAgJ;YAChJ,6GAA6G;YAC7G,0IAA0I;YAC1I,4HAA4H;YAC5H,4GAA4G;SAC7G;QACD,OAAO,EAAE;8CACiC;
|
|
1
|
+
{"version":3,"file":"lazy-loading.js","sourceRoot":"","sources":["../../src/rules/lazy-loading.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,WAAW,GAAS;IAC/B,EAAE,EAAE,cAAc;IAClB,KAAK,EAAE,gCAAgC;IACvC,QAAQ,EAAE,YAAY;IACtB,QAAQ,EAAE;QACR,OAAO;QACP,WAAW;QACX,kBAAkB;QAClB,gBAAgB;QAChB,iCAAiC;QACjC,SAAS;QACT,cAAc;QACd,cAAc;KACf;IACD,UAAU,EAAE,CAAC,cAAc,CAAC;IAC5B,MAAM,EAAE,gBAAgB;IACxB,KAAK,EAAE;QACL,SAAS,EACP,4XAA4X;QAC9X,OAAO,EAAE;iEACoD;QAC7D,MAAM,EACJ,uEAAuE;KAC1E;IACD,KAAK,EAAE;QACL,IAAI,EAAE,gFAAgF;QACtF,MAAM,EAAE;YACN,gJAAgJ;YAChJ,6GAA6G;YAC7G,0IAA0I;YAC1I,4HAA4H;YAC5H,4GAA4G;SAC7G;QACD,OAAO,EAAE;8CACiC;QAC1C,UAAU,EAAE;YACV,mGAAmG;YACnG,2EAA2E;SAC5E;KACF;IACD,MAAM,EAAE,CAAC,yBAAyB,CAAC;CACpC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"light-dark.d.ts","sourceRoot":"","sources":["../../src/rules/light-dark.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,SAAS,EAAE,IAqCvB,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export const lightDark = {
|
|
2
|
+
id: "light-dark",
|
|
3
|
+
title: "Light and dark theming",
|
|
4
|
+
category: "typography",
|
|
5
|
+
replaces: ["next-themes", "use-dark-mode", "theme-change"],
|
|
6
|
+
featureIds: ["light-dark", "color-scheme"],
|
|
7
|
+
native: "light-dark() with color-scheme",
|
|
8
|
+
human: {
|
|
9
|
+
explainer: "The usual setup declares every colour twice, once under a .dark class and once outside it, and ships JavaScript to move that class onto the html element before the first paint. light-dark() takes both values in one declaration and picks between them from the element's color-scheme, so a theme is one property rather than a class that has to be applied everywhere. Setting color-scheme on a subtree flips that subtree, which is how a manual toggle works without class plumbing.",
|
|
10
|
+
snippet: `:root {
|
|
11
|
+
/* Which of the two values below applies, and what the browser
|
|
12
|
+
paints for form controls and scrollbars. */
|
|
13
|
+
color-scheme: light dark;
|
|
14
|
+
--bg: light-dark(#ffffff, #111111);
|
|
15
|
+
--fg: light-dark(#111111, #f5f5f5);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/* A manual toggle sets color-scheme, and every token follows. */
|
|
19
|
+
[data-theme="dark"] { color-scheme: dark; }`,
|
|
20
|
+
mdnUrl: "https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/light-dark",
|
|
21
|
+
},
|
|
22
|
+
agent: {
|
|
23
|
+
when: "a site offers a light and a dark appearance",
|
|
24
|
+
unless: [
|
|
25
|
+
"You remember the choice across visits and cannot accept a flash of the wrong theme on first paint. Reading storage still needs a blocking inline script before the first paint, which is the part these libraries exist to get right.",
|
|
26
|
+
"You offer more than two themes, or themes that are not light and dark. light-dark() takes exactly two values, so a sepia or high-contrast option needs custom properties swapped per theme instead.",
|
|
27
|
+
"You read the resolved theme in JavaScript, for example to pick a chart palette or swap an image. CSS knows which branch applied and does not expose it, so that still needs matchMedia and your own state.",
|
|
28
|
+
"Your support target reaches below Chrome {{chrome:light-dark}}, Firefox {{firefox:light-dark}} or Safari {{safari:light-dark}}. light-dark() is newer than color-scheme by some years, so the surrounding property being safe is not proof this function is.",
|
|
29
|
+
],
|
|
30
|
+
snippet: "color-scheme: light dark;\ncolor: light-dark(#111, #eee);",
|
|
31
|
+
handRolled: [
|
|
32
|
+
"every colour token declared twice, once at the root and again under a .dark or [data-theme] selector",
|
|
33
|
+
"a prefers-color-scheme media query listener in JavaScript that toggles a class on documentElement",
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=light-dark.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"light-dark.js","sourceRoot":"","sources":["../../src/rules/light-dark.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,SAAS,GAAS;IAC7B,EAAE,EAAE,YAAY;IAChB,KAAK,EAAE,wBAAwB;IAC/B,QAAQ,EAAE,YAAY;IACtB,QAAQ,EAAE,CAAC,aAAa,EAAE,eAAe,EAAE,cAAc,CAAC;IAC1D,UAAU,EAAE,CAAC,YAAY,EAAE,cAAc,CAAC;IAC1C,MAAM,EAAE,gCAAgC;IACxC,KAAK,EAAE;QACL,SAAS,EACP,+dAA+d;QACje,OAAO,EAAE;;;;;;;;;4CAS+B;QACxC,MAAM,EACJ,yEAAyE;KAC5E;IACD,KAAK,EAAE;QACL,IAAI,EAAE,6CAA6C;QACnD,MAAM,EAAE;YACN,uOAAuO;YACvO,qMAAqM;YACrM,4MAA4M;YAC5M,8PAA8P;SAC/P;QACD,OAAO,EAAE,2DAA2D;QACpE,UAAU,EAAE;YACV,sGAAsG;YACtG,mGAAmG;SACpG;KACF;CACF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"line-clamp.d.ts","sourceRoot":"","sources":["../../src/rules/line-clamp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,SAAS,EAAE,
|
|
1
|
+
{"version":3,"file":"line-clamp.d.ts","sourceRoot":"","sources":["../../src/rules/line-clamp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,SAAS,EAAE,IA4CvB,CAAC"}
|
package/dist/rules/line-clamp.js
CHANGED
|
@@ -34,6 +34,10 @@ export const lineClamp = {
|
|
|
34
34
|
"You're relying on a build tool to add this prefix for you and it doesn't; -webkit-line-clamp still needs to be written by hand, autoprefixer tools do not treat it as one they add automatically in every configuration.",
|
|
35
35
|
],
|
|
36
36
|
snippet: ".excerpt { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; }",
|
|
37
|
+
handRolled: [
|
|
38
|
+
"measuring rendered text in a hidden element or on a canvas to decide where a line should visually end",
|
|
39
|
+
"slicing a string by character count before rendering it, so a card title fits its two lines",
|
|
40
|
+
],
|
|
37
41
|
},
|
|
38
42
|
};
|
|
39
43
|
//# sourceMappingURL=line-clamp.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"line-clamp.js","sourceRoot":"","sources":["../../src/rules/line-clamp.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,SAAS,GAAS;IAC7B,EAAE,EAAE,YAAY;IAChB,KAAK,EAAE,4BAA4B;IACnC,QAAQ,EAAE,YAAY;IACtB,QAAQ,EAAE;QACR,mBAAmB;QACnB,kBAAkB;QAClB,UAAU;QACV,YAAY;QACZ,WAAW;KACZ;IACD,UAAU,EAAE,EAAE;IACd,cAAc,EAAE;QACd,MAAM,EAAE,QAAQ;QAChB,UAAU,EAAE,YAAY;QACxB,IAAI,EAAE,maAAma;KAC1a;IACD,MAAM,EAAE,oBAAoB;IAC5B,KAAK,EAAE;QACL,SAAS,EACP,yVAAyV;QAC3V,OAAO,EAAE;;;;;EAKX;QACE,MAAM,EACJ,qEAAqE;KACxE;IACD,KAAK,EAAE;QACL,IAAI,EAAE,wEAAwE;QAC9E,MAAM,EAAE;YACN,oIAAoI;YACpI,4IAA4I;YAC5I,0NAA0N;SAC3N;QACD,OAAO,EACL,2GAA2G;
|
|
1
|
+
{"version":3,"file":"line-clamp.js","sourceRoot":"","sources":["../../src/rules/line-clamp.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,SAAS,GAAS;IAC7B,EAAE,EAAE,YAAY;IAChB,KAAK,EAAE,4BAA4B;IACnC,QAAQ,EAAE,YAAY;IACtB,QAAQ,EAAE;QACR,mBAAmB;QACnB,kBAAkB;QAClB,UAAU;QACV,YAAY;QACZ,WAAW;KACZ;IACD,UAAU,EAAE,EAAE;IACd,cAAc,EAAE;QACd,MAAM,EAAE,QAAQ;QAChB,UAAU,EAAE,YAAY;QACxB,IAAI,EAAE,maAAma;KAC1a;IACD,MAAM,EAAE,oBAAoB;IAC5B,KAAK,EAAE;QACL,SAAS,EACP,yVAAyV;QAC3V,OAAO,EAAE;;;;;EAKX;QACE,MAAM,EACJ,qEAAqE;KACxE;IACD,KAAK,EAAE;QACL,IAAI,EAAE,wEAAwE;QAC9E,MAAM,EAAE;YACN,oIAAoI;YACpI,4IAA4I;YAC5I,0NAA0N;SAC3N;QACD,OAAO,EACL,2GAA2G;QAC7G,UAAU,EAAE;YACV,uGAAuG;YACvG,6FAA6F;SAC9F;KACF;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-format.d.ts","sourceRoot":"","sources":["../../src/rules/list-format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,UAAU,EAAE,IAwCxB,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export const listFormat = {
|
|
2
|
+
id: "intl-list-format",
|
|
3
|
+
title: "Joining a list into a sentence",
|
|
4
|
+
category: "formatting",
|
|
5
|
+
replaces: ["humanize-list"],
|
|
6
|
+
featureIds: ["intl-list-format"],
|
|
7
|
+
native: "Intl.ListFormat",
|
|
8
|
+
human: {
|
|
9
|
+
explainer: 'Commas between the items and an "and" before the last one looks like string work until there is a second language. Intl.ListFormat renders the list with the separators and the conjunction the locale actually uses, so English gets its serial comma and German gets "und" without either being written down. It also handles disjunctions, where the joining word is "or", and plain unit lists with no conjunction at all.',
|
|
10
|
+
snippet: `const fmt = new Intl.ListFormat("en", { type: "conjunction" });
|
|
11
|
+
fmt.format(["apples", "pears", "plums"]);
|
|
12
|
+
// "apples, pears, and plums"
|
|
13
|
+
|
|
14
|
+
new Intl.ListFormat("de").format(["Äpfel", "Birnen", "Pflaumen"]);
|
|
15
|
+
// "Äpfel, Birnen und Pflaumen"
|
|
16
|
+
|
|
17
|
+
new Intl.ListFormat("en", { type: "disjunction" }).format(["red", "blue"]);
|
|
18
|
+
// "red or blue"`,
|
|
19
|
+
mdnUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat",
|
|
20
|
+
},
|
|
21
|
+
agent: {
|
|
22
|
+
when: 'joining several items into one phrase, such as "apples, pears, and plums"',
|
|
23
|
+
unless: [
|
|
24
|
+
'You truncate long lists, as in "Ana, Ben and 4 others". Intl.ListFormat renders every item it is given, so deciding how many to show and building the "and N more" item stays your code.',
|
|
25
|
+
"You need a separator the locale does not use, such as joining with a slash or a bullet for a breadcrumb. That is Array.prototype.join, and neither the library nor Intl is involved.",
|
|
26
|
+
"The items are not already strings. format() throws a TypeError on anything else, where humanize-list coerces, so numbers and nulls that used to render now break.",
|
|
27
|
+
"You depend on humanize-list's exact output, including its oxfordComma option. Intl follows the locale's own convention, so switching changes visible text in English.",
|
|
28
|
+
"You need each item wrapped in markup. formatToParts() gives you the pieces and their types, but reassembling them into elements is work the plain format() call does not do.",
|
|
29
|
+
],
|
|
30
|
+
snippet: `new Intl.ListFormat("en", { type: "conjunction" }).format([
|
|
31
|
+
"apples",
|
|
32
|
+
"pears",
|
|
33
|
+
"plums",
|
|
34
|
+
]);`,
|
|
35
|
+
handRolled: [
|
|
36
|
+
'slice(0, -1).join(", ") joined to the last item with " and ", plus length checks for the one and two item cases',
|
|
37
|
+
],
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=list-format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-format.js","sourceRoot":"","sources":["../../src/rules/list-format.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,UAAU,GAAS;IAC9B,EAAE,EAAE,kBAAkB;IACtB,KAAK,EAAE,gCAAgC;IACvC,QAAQ,EAAE,YAAY;IACtB,QAAQ,EAAE,CAAC,eAAe,CAAC;IAC3B,UAAU,EAAE,CAAC,kBAAkB,CAAC;IAChC,MAAM,EAAE,iBAAiB;IACzB,KAAK,EAAE;QACL,SAAS,EACP,gaAAga;QACla,OAAO,EAAE;;;;;;;;iBAQI;QACb,MAAM,EACJ,kGAAkG;KACrG;IACD,KAAK,EAAE;QACL,IAAI,EAAE,2EAA2E;QACjF,MAAM,EAAE;YACN,0LAA0L;YAC1L,sLAAsL;YACtL,mKAAmK;YACnK,uKAAuK;YACvK,8KAA8K;SAC/K;QACD,OAAO,EAAE;;;;IAIT;QACA,UAAU,EAAE;YACV,iHAAiH;SAClH;KACF;CACF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"masonry.d.ts","sourceRoot":"","sources":["../../src/rules/masonry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"masonry.d.ts","sourceRoot":"","sources":["../../src/rules/masonry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,OAAO,EAAE,IAgErB,CAAC"}
|
package/dist/rules/masonry.js
CHANGED
|
@@ -55,6 +55,10 @@ export const masonry = {
|
|
|
55
55
|
.gallery { columns: 16rem; }
|
|
56
56
|
.gallery > * { break-inside: avoid; }
|
|
57
57
|
}`,
|
|
58
|
+
handRolled: [
|
|
59
|
+
"distributing items into column arrays in JavaScript by tracking each column's running height",
|
|
60
|
+
"absolutely positioning items after measuring them so the gaps between rows close up",
|
|
61
|
+
],
|
|
58
62
|
},
|
|
59
63
|
};
|
|
60
64
|
//# sourceMappingURL=masonry.js.map
|
|
@@ -1 +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,QAAQ;IAClB,QAAQ,EAAE;QACR,mBAAmB;QACnB,gBAAgB;QAChB,yBAAyB;QACzB,OAAO;QACP,qBAAqB;QACrB,aAAa;QACb,iBAAiB;KAClB;IACD,UAAU,EAAE,CAAC,SAAS,CAAC;IACvB,MAAM,EAAE,4BAA4B;IACpC,KAAK,EAAE;QACL,SAAS,EACP,wiBAAwiB;QAC1iB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;EAoBX;QACE,MAAM,EACJ,iFAAiF;KACpF;IACD,KAAK,EAAE;QACL,IAAI,EAAE,uFAAuF;QAC7F,MAAM,EAAE;YACN,8LAA8L;YAC9L,6EAA6E;YAC7E,iEAAiE;YACjE,yHAAyH;SAC1H;QACD,OAAO,EAAE;;;;;;;;EAQX;
|
|
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,QAAQ;IAClB,QAAQ,EAAE;QACR,mBAAmB;QACnB,gBAAgB;QAChB,yBAAyB;QACzB,OAAO;QACP,qBAAqB;QACrB,aAAa;QACb,iBAAiB;KAClB;IACD,UAAU,EAAE,CAAC,SAAS,CAAC;IACvB,MAAM,EAAE,4BAA4B;IACpC,KAAK,EAAE;QACL,SAAS,EACP,wiBAAwiB;QAC1iB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;EAoBX;QACE,MAAM,EACJ,iFAAiF;KACpF;IACD,KAAK,EAAE;QACL,IAAI,EAAE,uFAAuF;QAC7F,MAAM,EAAE;YACN,8LAA8L;YAC9L,6EAA6E;YAC7E,iEAAiE;YACjE,yHAAyH;SAC1H;QACD,OAAO,EAAE;;;;;;;;EAQX;QACE,UAAU,EAAE;YACV,8FAA8F;YAC9F,qFAAqF;SACtF;KACF;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"match-media.d.ts","sourceRoot":"","sources":["../../src/rules/match-media.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,UAAU,EAAE,IAoCxB,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export const matchMedia = {
|
|
2
|
+
id: "match-media",
|
|
3
|
+
title: "Reacting to a breakpoint",
|
|
4
|
+
category: "layout",
|
|
5
|
+
replaces: ["react-responsive", "react-media", "use-media", "enquire.js"],
|
|
6
|
+
featureIds: ["matchmedia"],
|
|
7
|
+
native: "matchMedia()",
|
|
8
|
+
human: {
|
|
9
|
+
explainer: "These libraries wrap one method. matchMedia() takes the same query string a stylesheet would, reports whether it matches now, and fires an event when that changes, with no resize listener and no width arithmetic. Most uses of them are styling rather than logic, and a media or container query in CSS handles those without JavaScript running at all.",
|
|
10
|
+
snippet: `const wide = matchMedia("(min-width: 48rem)");
|
|
11
|
+
|
|
12
|
+
function apply(event) {
|
|
13
|
+
// Same shape for the initial read and every later change.
|
|
14
|
+
setColumns(event.matches ? 3 : 1);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
apply(wide);
|
|
18
|
+
wide.addEventListener("change", apply);`,
|
|
19
|
+
mdnUrl: "https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia",
|
|
20
|
+
},
|
|
21
|
+
agent: {
|
|
22
|
+
when: "JavaScript needs to know whether a media query currently matches",
|
|
23
|
+
unless: [
|
|
24
|
+
"You server-render and need the first paint to be right. matchMedia does not exist on the server and the client's first read happens after hydration, so a wrong first frame or a mismatch warning is the failure mode these libraries put real work into avoiding.",
|
|
25
|
+
"You are changing appearance rather than behaviour. A media query or a container query does that in CSS, which is fewer moving parts than either the library or this API.",
|
|
26
|
+
"You query an element's size rather than the viewport's. matchMedia only answers about the viewport and the device, so a component that responds to its own box needs a container query or ResizeObserver.",
|
|
27
|
+
"The library's other features are in use, such as react-responsive's device-property shorthands or its context-based overriding for tests.",
|
|
28
|
+
],
|
|
29
|
+
snippet: 'matchMedia("(min-width: 48rem)").matches;',
|
|
30
|
+
handRolled: [
|
|
31
|
+
"a resize listener comparing window.innerWidth against a breakpoint number kept in JavaScript",
|
|
32
|
+
"an isMobile flag held in state and recomputed from innerWidth inside a debounced resize handler",
|
|
33
|
+
],
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=match-media.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"match-media.js","sourceRoot":"","sources":["../../src/rules/match-media.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,UAAU,GAAS;IAC9B,EAAE,EAAE,aAAa;IACjB,KAAK,EAAE,0BAA0B;IACjC,QAAQ,EAAE,QAAQ;IAClB,QAAQ,EAAE,CAAC,kBAAkB,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,CAAC;IACxE,UAAU,EAAE,CAAC,YAAY,CAAC;IAC1B,MAAM,EAAE,cAAc;IACtB,KAAK,EAAE;QACL,SAAS,EACP,8VAA8V;QAChW,OAAO,EAAE;;;;;;;;wCAQ2B;QACpC,MAAM,EACJ,oEAAoE;KACvE;IACD,KAAK,EAAE;QACL,IAAI,EAAE,kEAAkE;QACxE,MAAM,EAAE;YACN,oQAAoQ;YACpQ,0KAA0K;YAC1K,2MAA2M;YAC3M,2IAA2I;SAC5I;QACD,OAAO,EAAE,2CAA2C;QACpD,UAAU,EAAE;YACV,8FAA8F;YAC9F,iGAAiG;SAClG;KACF;CACF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"natural-sort.d.ts","sourceRoot":"","sources":["../../src/rules/natural-sort.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"natural-sort.d.ts","sourceRoot":"","sources":["../../src/rules/natural-sort.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,WAAW,EAAE,IA6CzB,CAAC"}
|
|
@@ -36,6 +36,10 @@ export const naturalSort = {
|
|
|
36
36
|
],
|
|
37
37
|
snippet: `const collator = new Intl.Collator(undefined, { numeric: true });
|
|
38
38
|
list.sort(collator.compare);`,
|
|
39
|
+
handRolled: [
|
|
40
|
+
"a comparator pulling digits out of strings with a regex and comparing them as numbers",
|
|
41
|
+
"zero-padding numbers inside strings so a plain sort puts item10 after item9",
|
|
42
|
+
],
|
|
39
43
|
},
|
|
40
44
|
};
|
|
41
45
|
//# sourceMappingURL=natural-sort.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"natural-sort.js","sourceRoot":"","sources":["../../src/rules/natural-sort.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,WAAW,GAAS;IAC/B,EAAE,EAAE,cAAc;IAClB,KAAK,EAAE,kCAAkC;IACzC,QAAQ,EAAE,YAAY;IACtB,QAAQ,EAAE;QACR,iBAAiB;QACjB,sBAAsB;QACtB,iBAAiB;QACjB,wBAAwB;KACzB;IACD,UAAU,EAAE,CAAC,MAAM,CAAC;IACpB,MAAM,EAAE,kCAAkC;IAC1C,KAAK,EAAE;QACL,SAAS,EACP,kYAAkY;QACpY,OAAO,EAAE;;;;;;;;;;2BAUc;QACvB,MAAM,EACJ,gGAAgG;KACnG;IACD,KAAK,EAAE;QACL,IAAI,EAAE,qEAAqE;QAC3E,MAAM,EAAE;YACN,uMAAuM;YACvM,kKAAkK;YAClK,mKAAmK;YACnK,6IAA6I;YAC7I,6IAA6I;SAC9I;QACD,OAAO,EAAE;6BACgB;
|
|
1
|
+
{"version":3,"file":"natural-sort.js","sourceRoot":"","sources":["../../src/rules/natural-sort.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,WAAW,GAAS;IAC/B,EAAE,EAAE,cAAc;IAClB,KAAK,EAAE,kCAAkC;IACzC,QAAQ,EAAE,YAAY;IACtB,QAAQ,EAAE;QACR,iBAAiB;QACjB,sBAAsB;QACtB,iBAAiB;QACjB,wBAAwB;KACzB;IACD,UAAU,EAAE,CAAC,MAAM,CAAC;IACpB,MAAM,EAAE,kCAAkC;IAC1C,KAAK,EAAE;QACL,SAAS,EACP,kYAAkY;QACpY,OAAO,EAAE;;;;;;;;;;2BAUc;QACvB,MAAM,EACJ,gGAAgG;KACnG;IACD,KAAK,EAAE;QACL,IAAI,EAAE,qEAAqE;QAC3E,MAAM,EAAE;YACN,uMAAuM;YACvM,kKAAkK;YAClK,mKAAmK;YACnK,6IAA6I;YAC7I,6IAA6I;SAC9I;QACD,OAAO,EAAE;6BACgB;QACzB,UAAU,EAAE;YACV,uFAAuF;YACvF,6EAA6E;SAC9E;KACF;CACF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"number-format.d.ts","sourceRoot":"","sources":["../../src/rules/number-format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"number-format.d.ts","sourceRoot":"","sources":["../../src/rules/number-format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,YAAY,EAAE,IAyC1B,CAAC"}
|
|
@@ -2,7 +2,14 @@ export const numberFormat = {
|
|
|
2
2
|
id: "number-format",
|
|
3
3
|
title: "Locale-aware number and currency formatting",
|
|
4
4
|
category: "formatting",
|
|
5
|
-
replaces: [
|
|
5
|
+
replaces: [
|
|
6
|
+
"numeral",
|
|
7
|
+
"accounting",
|
|
8
|
+
"currency.js",
|
|
9
|
+
"format-number",
|
|
10
|
+
"pretty-bytes",
|
|
11
|
+
"filesize",
|
|
12
|
+
],
|
|
6
13
|
featureIds: ["intl"],
|
|
7
14
|
native: "Intl.NumberFormat",
|
|
8
15
|
human: {
|
|
@@ -19,9 +26,15 @@ export const numberFormat = {
|
|
|
19
26
|
'You format units or compact notation. style: "unit" and notation: "compact" arrived long after the rest of Intl.NumberFormat, in Chrome {{chrome:javascript.builtins.Intl.NumberFormat.NumberFormat.options_parameter.options_unit_parameter}}, Firefox {{firefox:javascript.builtins.Intl.NumberFormat.NumberFormat.options_parameter.options_unit_parameter}} and Safari {{safari:javascript.builtins.Intl.NumberFormat.NumberFormat.options_parameter.options_unit_parameter}}, so an older target does not get them.',
|
|
20
27
|
"You need safe decimal arithmetic, such as adding money values without floating-point rounding errors. currency.js and accounting.js do that math for you; Intl.NumberFormat only formats a number you already computed correctly.",
|
|
21
28
|
"You need to parse a formatted string back into a number. Intl.NumberFormat is format-only; these libraries often provide the reverse direction too.",
|
|
29
|
+
'You format byte sizes and need the unit chosen for you. Intl.NumberFormat formats a magnitude you already picked, so "kilobyte" on 1200 prints 1,200 kB rather than 1.2 MB, and dividing down to the right unit first is the part pretty-bytes and filesize actually do.',
|
|
30
|
+
"You need binary units. The sanctioned unit list has no kibibyte, mebibyte or gibibyte, and asking for one throws a RangeError rather than falling back, so anything reporting KiB or MiB keeps its library.",
|
|
22
31
|
"You need a custom format pattern, such as a specific abbreviation style, that the options Intl.NumberFormat exposes cannot express.",
|
|
23
32
|
],
|
|
24
33
|
snippet: 'new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" }).format(value);',
|
|
34
|
+
handRolled: [
|
|
35
|
+
"a regex inserting thousands separators into a number's string form",
|
|
36
|
+
"toFixed followed by string surgery to add a currency symbol and group the digits",
|
|
37
|
+
],
|
|
25
38
|
},
|
|
26
39
|
};
|
|
27
40
|
//# sourceMappingURL=number-format.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"number-format.js","sourceRoot":"","sources":["../../src/rules/number-format.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,YAAY,GAAS;IAChC,EAAE,EAAE,eAAe;IACnB,KAAK,EAAE,6CAA6C;IACpD,QAAQ,EAAE,YAAY;IACtB,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"number-format.js","sourceRoot":"","sources":["../../src/rules/number-format.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,YAAY,GAAS;IAChC,EAAE,EAAE,eAAe;IACnB,KAAK,EAAE,6CAA6C;IACpD,QAAQ,EAAE,YAAY;IACtB,QAAQ,EAAE;QACR,SAAS;QACT,YAAY;QACZ,aAAa;QACb,eAAe;QACf,cAAc;QACd,UAAU;KACX;IACD,UAAU,EAAE,CAAC,MAAM,CAAC;IACpB,MAAM,EAAE,mBAAmB;IAC3B,KAAK,EAAE;QACL,SAAS,EACP,wZAAwZ;QAC1Z,OAAO,EAAE;;;kCAGqB;QAC9B,MAAM,EACJ,oGAAoG;KACvG;IACD,KAAK,EAAE;QACL,IAAI,EAAE,yGAAyG;QAC/G,MAAM,EAAE;YACN,0fAA0f;YAC1f,mOAAmO;YACnO,qJAAqJ;YACrJ,0QAA0Q;YAC1Q,6MAA6M;YAC7M,qIAAqI;SACtI;QACD,OAAO,EACL,uFAAuF;QACzF,UAAU,EAAE;YACV,oEAAoE;YACpE,kFAAkF;SACnF;KACF;CACF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page-visibility.d.ts","sourceRoot":"","sources":["../../src/rules/page-visibility.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,cAAc,EAAE,
|
|
1
|
+
{"version":3,"file":"page-visibility.d.ts","sourceRoot":"","sources":["../../src/rules/page-visibility.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,cAAc,EAAE,IAgC5B,CAAC"}
|
|
@@ -20,6 +20,9 @@ export const pageVisibility = {
|
|
|
20
20
|
"You need to distinguish a window occluded by another window from a genuinely backgrounded tab. visibilityState only reports the latter.",
|
|
21
21
|
],
|
|
22
22
|
snippet: `document.addEventListener("visibilitychange", () => { ... });`,
|
|
23
|
+
handRolled: [
|
|
24
|
+
"a blur handler standing in for the tab being backgrounded, pausing a poll that a focus handler resumes",
|
|
25
|
+
],
|
|
23
26
|
},
|
|
24
27
|
guides: [
|
|
25
28
|
"detect-initial-visibility-state",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page-visibility.js","sourceRoot":"","sources":["../../src/rules/page-visibility.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,cAAc,GAAS;IAClC,EAAE,EAAE,iBAAiB;IACrB,KAAK,EAAE,gBAAgB;IACvB,QAAQ,EAAE,YAAY;IACtB,QAAQ,EAAE,CAAC,uBAAuB,EAAE,cAAc,CAAC;IACnD,UAAU,EAAE,CAAC,iBAAiB,CAAC;IAC/B,MAAM,EAAE,yDAAyD;IACjE,KAAK,EAAE;QACL,SAAS,EACP,wRAAwR;QAC1R,OAAO,EAAE;;;IAGT;QACA,MAAM,EACJ,kFAAkF;KACrF;IACD,KAAK,EAAE;QACL,IAAI,EAAE,kGAAkG;QACxG,MAAM,EAAE;YACN,+GAA+G;YAC/G,yIAAyI;SAC1I;QACD,OAAO,EAAE,+DAA+D;
|
|
1
|
+
{"version":3,"file":"page-visibility.js","sourceRoot":"","sources":["../../src/rules/page-visibility.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,cAAc,GAAS;IAClC,EAAE,EAAE,iBAAiB;IACrB,KAAK,EAAE,gBAAgB;IACvB,QAAQ,EAAE,YAAY;IACtB,QAAQ,EAAE,CAAC,uBAAuB,EAAE,cAAc,CAAC;IACnD,UAAU,EAAE,CAAC,iBAAiB,CAAC;IAC/B,MAAM,EAAE,yDAAyD;IACjE,KAAK,EAAE;QACL,SAAS,EACP,wRAAwR;QAC1R,OAAO,EAAE;;;IAGT;QACA,MAAM,EACJ,kFAAkF;KACrF;IACD,KAAK,EAAE;QACL,IAAI,EAAE,kGAAkG;QACxG,MAAM,EAAE;YACN,+GAA+G;YAC/G,yIAAyI;SAC1I;QACD,OAAO,EAAE,+DAA+D;QACxE,UAAU,EAAE;YACV,wGAAwG;SACzG;KACF;IACD,MAAM,EAAE;QACN,iCAAiC;QACjC,iCAAiC;KAClC;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"passkeys.d.ts","sourceRoot":"","sources":["../../src/rules/passkeys.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,QAAQ,EAAE,IA6CtB,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export const passkeys = {
|
|
2
|
+
id: "passkeys",
|
|
3
|
+
title: "Passkeys in the browser",
|
|
4
|
+
category: "device-apis",
|
|
5
|
+
replaces: ["@simplewebauthn/browser"],
|
|
6
|
+
featureIds: [],
|
|
7
|
+
manualBaseline: {
|
|
8
|
+
status: "newly",
|
|
9
|
+
verifiedOn: "2026-09-20",
|
|
10
|
+
note: "web-features has no ID for the JSON helpers this rule turns on, and they sit inside the 'webauthn' feature's own compat data rather than beside it. Deriving from that ID would badge this widely available on the ceremony's dates, Safari {{safari:webauthn}}, while the parseCreationOptionsFromJSON and toJSON calls that remove the need for a wrapper arrived in Safari {{safari:api.PublicKeyCredential.parseCreationOptionsFromJSON_static}}, Chrome {{chrome:api.PublicKeyCredential.parseCreationOptionsFromJSON_static}} and Firefox {{firefox:api.PublicKeyCredential.parseCreationOptionsFromJSON_static}}. Newly available on the helpers' own dates: the last engine shipped them in March 2025.",
|
|
11
|
+
},
|
|
12
|
+
native: "navigator.credentials with PublicKeyCredential",
|
|
13
|
+
human: {
|
|
14
|
+
explainer: "The browser half of a passkey flow is two calls: create() to register a credential and get() to sign a challenge. The reason a wrapper existed is that both used to need every challenge and id field converted to and from base64url by hand. parseCreationOptionsFromJSON and toJSON now do that conversion in the browser, so the server's JSON goes in and the response comes back out in the same shape.",
|
|
15
|
+
snippet: `// The server sends JSON; the browser parses it into the
|
|
16
|
+
// ArrayBuffer-shaped options the call expects.
|
|
17
|
+
const options = PublicKeyCredential.parseCreationOptionsFromJSON(fromServer);
|
|
18
|
+
const credential = await navigator.credentials.create({
|
|
19
|
+
publicKey: options,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// And back to JSON for the response, without hand-rolled base64url.
|
|
23
|
+
await fetch("/register", {
|
|
24
|
+
method: "POST",
|
|
25
|
+
body: JSON.stringify(credential.toJSON()),
|
|
26
|
+
});`,
|
|
27
|
+
mdnUrl: "https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API",
|
|
28
|
+
},
|
|
29
|
+
agent: {
|
|
30
|
+
when: "registering or authenticating a passkey from the browser",
|
|
31
|
+
unless: [
|
|
32
|
+
"Your support target reaches below Chrome {{chrome:api.PublicKeyCredential.parseCreationOptionsFromJSON_static}}, Firefox {{firefox:api.PublicKeyCredential.parseCreationOptionsFromJSON_static}} or Safari {{safari:api.PublicKeyCredential.parseCreationOptionsFromJSON_static}}. The ceremony itself is years older than those, so the credential calls work while the JSON helpers that make the wrapper unnecessary do not, and the base64url conversion comes back.",
|
|
33
|
+
"You use the library's server package as well. @simplewebauthn/server generates and verifies the challenge, and the platform has no counterpart for that: this covers the browser side only.",
|
|
34
|
+
"You rely on the library's browser-capability helpers, such as its checks for a platform authenticator or for conditional UI, which are feature detection it has already written.",
|
|
35
|
+
"You need the same code path on a browser where conditional mediation behaves differently, which the library smooths over and the raw call does not.",
|
|
36
|
+
],
|
|
37
|
+
snippet: "const credential = await navigator.credentials.get({ publicKey: options });",
|
|
38
|
+
handRolled: [
|
|
39
|
+
"base64url encode and decode helpers written next to a credentials.create call to convert challenge and id fields",
|
|
40
|
+
"a Uint8Array built by looping over atob output to turn a server challenge into bytes",
|
|
41
|
+
],
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=passkeys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"passkeys.js","sourceRoot":"","sources":["../../src/rules/passkeys.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,QAAQ,GAAS;IAC5B,EAAE,EAAE,UAAU;IACd,KAAK,EAAE,yBAAyB;IAChC,QAAQ,EAAE,aAAa;IACvB,QAAQ,EAAE,CAAC,yBAAyB,CAAC;IACrC,UAAU,EAAE,EAAE;IACd,cAAc,EAAE;QACd,MAAM,EAAE,OAAO;QACf,UAAU,EAAE,YAAY;QACxB,IAAI,EAAE,irBAAirB;KACxrB;IACD,MAAM,EAAE,gDAAgD;IACxD,KAAK,EAAE;QACL,SAAS,EACP,+YAA+Y;QACjZ,OAAO,EAAE;;;;;;;;;;;IAWT;QACA,MAAM,EACJ,yEAAyE;KAC5E;IACD,KAAK,EAAE;QACL,IAAI,EAAE,0DAA0D;QAChE,MAAM,EAAE;YACN,0cAA0c;YAC1c,6LAA6L;YAC7L,kLAAkL;YAClL,qJAAqJ;SACtJ;QACD,OAAO,EACL,6EAA6E;QAC/E,UAAU,EAAE;YACV,kHAAkH;YAClH,sFAAsF;SACvF;KACF;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plural-rules.d.ts","sourceRoot":"","sources":["../../src/rules/plural-rules.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,WAAW,EAAE,IAkCzB,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export const pluralRules = {
|
|
2
|
+
id: "plural-rules",
|
|
3
|
+
title: "Choosing a plural form",
|
|
4
|
+
category: "formatting",
|
|
5
|
+
replaces: ["pluralize"],
|
|
6
|
+
featureIds: ["intl-plural-rules"],
|
|
7
|
+
native: "Intl.PluralRules",
|
|
8
|
+
human: {
|
|
9
|
+
explainer: 'Picking between "1 file" and "2 files" by testing count === 1 is only correct in English, and barely. Russian needs one form for 3 and another for 5, and Polish and Arabic have more. Intl.PluralRules answers which category a number falls into for a locale, so the branching stops being a guess. It returns the category rather than the word, which is the part worth knowing before reaching for it.',
|
|
10
|
+
snippet: `const pr = new Intl.PluralRules("en-US");
|
|
11
|
+
const forms = { one: "file", other: "files" };
|
|
12
|
+
\`\${count} \${forms[pr.select(count)]}\`; // "1 file", "2 files"
|
|
13
|
+
|
|
14
|
+
// Ordinals are the same API with a different type.
|
|
15
|
+
new Intl.PluralRules("en-US", { type: "ordinal" }).select(22); // "two"`,
|
|
16
|
+
mdnUrl: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/PluralRules",
|
|
17
|
+
},
|
|
18
|
+
agent: {
|
|
19
|
+
when: "choosing between singular and plural wording for a count",
|
|
20
|
+
unless: [
|
|
21
|
+
'You need the plural word itself. Intl.PluralRules returns a category such as "one" or "other" and never inflects anything, so "person" to "people" and "index" to "indices" still need pluralize or a table of your own. This is the difference that decides most cases.',
|
|
22
|
+
"You pluralise arbitrary nouns you do not control, such as user-supplied or database-driven labels. A category is only useful when you already hold both forms, which you cannot if the noun is unknown at build time.",
|
|
23
|
+
"You singularise as well as pluralise. pluralize goes both directions and this API goes neither.",
|
|
24
|
+
"Your strings already run through an ICU message catalogue. It has plural selection built in and doing it twice is how the two disagree.",
|
|
25
|
+
],
|
|
26
|
+
snippet: 'new Intl.PluralRules(locale).select(count); // "one" | "other" | ...',
|
|
27
|
+
handRolled: [
|
|
28
|
+
'a count === 1 ternary picking between two words, or a bare + "s" appended to a noun',
|
|
29
|
+
"a lookup of irregular plurals kept next to the component that renders them",
|
|
30
|
+
],
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=plural-rules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plural-rules.js","sourceRoot":"","sources":["../../src/rules/plural-rules.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,WAAW,GAAS;IAC/B,EAAE,EAAE,cAAc;IAClB,KAAK,EAAE,wBAAwB;IAC/B,QAAQ,EAAE,YAAY;IACtB,QAAQ,EAAE,CAAC,WAAW,CAAC;IACvB,UAAU,EAAE,CAAC,mBAAmB,CAAC;IACjC,MAAM,EAAE,kBAAkB;IAC1B,KAAK,EAAE;QACL,SAAS,EACP,8YAA8Y;QAChZ,OAAO,EAAE;;;;;wEAK2D;QACpE,MAAM,EACJ,mGAAmG;KACtG;IACD,KAAK,EAAE;QACL,IAAI,EAAE,0DAA0D;QAChE,MAAM,EAAE;YACN,0QAA0Q;YAC1Q,uNAAuN;YACvN,iGAAiG;YACjG,yIAAyI;SAC1I;QACD,OAAO,EACL,sEAAsE;QACxE,UAAU,EAAE;YACV,qFAAqF;YACrF,4EAA4E;SAC7E;KACF;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pointer-events.d.ts","sourceRoot":"","sources":["../../src/rules/pointer-events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,aAAa,EAAE,IA2C3B,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export const pointerEvents = {
|
|
2
|
+
id: "pointer-events",
|
|
3
|
+
title: "Touch and pointer gestures",
|
|
4
|
+
category: "device-apis",
|
|
5
|
+
replaces: ["hammerjs", "react-swipeable", "swiped-events"],
|
|
6
|
+
featureIds: ["pointer-events-api"],
|
|
7
|
+
native: "pointer events with touch-action",
|
|
8
|
+
human: {
|
|
9
|
+
explainer: "hammerjs was written when mouse and touch were separate event streams that had to be normalised, and it has not been maintained since 2016. Pointer events deliver both through one set of handlers, with pointerId to tell fingers apart and setPointerCapture so a drag keeps reporting after the pointer leaves the element. A swipe is a pointerdown coordinate, a pointerup coordinate, and a threshold.",
|
|
10
|
+
snippet: `let startX = 0;
|
|
11
|
+
|
|
12
|
+
el.addEventListener("pointerdown", (event) => {
|
|
13
|
+
startX = event.clientX;
|
|
14
|
+
// Keeps events coming even if the pointer leaves the element.
|
|
15
|
+
el.setPointerCapture(event.pointerId);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
el.addEventListener("pointerup", (event) => {
|
|
19
|
+
const dx = event.clientX - startX;
|
|
20
|
+
if (Math.abs(dx) > 50) onSwipe(dx > 0 ? "right" : "left");
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// Tell the browser which direction you are handling, so it keeps
|
|
24
|
+
// vertical scrolling for itself. In CSS: touch-action: pan-y.
|
|
25
|
+
el.style.touchAction = "pan-y";`,
|
|
26
|
+
mdnUrl: "https://developer.mozilla.org/en-US/docs/Web/API/Pointer_events",
|
|
27
|
+
},
|
|
28
|
+
agent: {
|
|
29
|
+
when: "handling swipes, drags or other pointer gestures",
|
|
30
|
+
unless: [
|
|
31
|
+
"You need multi-touch recognisers such as pinch to zoom or two-finger rotate. Tracking several pointerIds and deriving the transform between them is real geometry, and it is most of what hammerjs is.",
|
|
32
|
+
"You need velocity, direction and threshold tuning that already feels right. A naive distance check fires on a slow drag that was never meant as a swipe, and the tuned version is the library's actual value.",
|
|
33
|
+
"You rely on hammerjs recognisers with conflict resolution between them, such as pan and swipe on the same element, where the ordering is configured rather than written.",
|
|
34
|
+
"Your support target reaches below Chrome {{chrome:pointer-events-api}}, Firefox {{firefox:pointer-events-api}} or Safari {{safari:pointer-events-api}}, which came to pointer events considerably later than the others.",
|
|
35
|
+
],
|
|
36
|
+
snippet: 'el.addEventListener("pointerdown", (e) => el.setPointerCapture(e.pointerId));',
|
|
37
|
+
handRolled: [
|
|
38
|
+
"paired touchstart and touchend listeners reading changedTouches[0].clientX to work out a swipe direction",
|
|
39
|
+
"separate mousedown and touchstart branches doing the same thing, written because the two event streams disagree",
|
|
40
|
+
],
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=pointer-events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pointer-events.js","sourceRoot":"","sources":["../../src/rules/pointer-events.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,aAAa,GAAS;IACjC,EAAE,EAAE,gBAAgB;IACpB,KAAK,EAAE,4BAA4B;IACnC,QAAQ,EAAE,aAAa;IACvB,QAAQ,EAAE,CAAC,UAAU,EAAE,iBAAiB,EAAE,eAAe,CAAC;IAC1D,UAAU,EAAE,CAAC,oBAAoB,CAAC;IAClC,MAAM,EAAE,kCAAkC;IAC1C,KAAK,EAAE;QACL,SAAS,EACP,+YAA+Y;QACjZ,OAAO,EAAE;;;;;;;;;;;;;;;gCAemB;QAC5B,MAAM,EAAE,iEAAiE;KAC1E;IACD,KAAK,EAAE;QACL,IAAI,EAAE,kDAAkD;QACxD,MAAM,EAAE;YACN,wMAAwM;YACxM,+MAA+M;YAC/M,0KAA0K;YAC1K,0NAA0N;SAC3N;QACD,OAAO,EACL,+EAA+E;QACjF,UAAU,EAAE;YACV,0GAA0G;YAC1G,iHAAiH;SAClH;KACF;CACF,CAAC"}
|
|
@@ -1 +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,
|
|
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,IA4ErB,CAAC"}
|
package/dist/rules/popover.js
CHANGED
|
@@ -62,6 +62,11 @@ export const popover = {
|
|
|
62
62
|
position-try-fallbacks: flip-block;
|
|
63
63
|
}
|
|
64
64
|
</style>`,
|
|
65
|
+
handRolled: [
|
|
66
|
+
"calling getBoundingClientRect on a trigger inside scroll and resize listeners to place a floating panel",
|
|
67
|
+
"writing top and left onto a tooltip from a requestAnimationFrame loop",
|
|
68
|
+
"flip logic comparing a panel's rect against the viewport and moving it to the other side of its trigger",
|
|
69
|
+
],
|
|
65
70
|
},
|
|
66
71
|
guides: [
|
|
67
72
|
"position-aware-tooltips",
|
|
@@ -1 +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,OAAO;IACjB,QAAQ,EAAE;QACR,oBAAoB;QACpB,wBAAwB;QACxB,kBAAkB;QAClB,gBAAgB;QAChB,WAAW;QACX,UAAU;QACV,gBAAgB;QAChB,cAAc;QACd,eAAe;QACf,cAAc;QACd,WAAW;QACX,2BAA2B;KAC5B;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;QACtD,MAAM,EAAE,8DAA8D;KACvE;IACD,KAAK,EAAE;QACL,IAAI,EAAE,oEAAoE;QAC1E,MAAM,EAAE;YACN,uUAAuU;YACvU,iIAAiI;YACjI,0DAA0D;YAC1D,iHAAiH;YACjH,uEAAuE;SACxE;QACD,OAAO,EAAE;;;;;;;;;;SAUJ;
|
|
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,OAAO;IACjB,QAAQ,EAAE;QACR,oBAAoB;QACpB,wBAAwB;QACxB,kBAAkB;QAClB,gBAAgB;QAChB,WAAW;QACX,UAAU;QACV,gBAAgB;QAChB,cAAc;QACd,eAAe;QACf,cAAc;QACd,WAAW;QACX,2BAA2B;KAC5B;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;QACtD,MAAM,EAAE,8DAA8D;KACvE;IACD,KAAK,EAAE;QACL,IAAI,EAAE,oEAAoE;QAC1E,MAAM,EAAE;YACN,uUAAuU;YACvU,iIAAiI;YACjI,0DAA0D;YAC1D,iHAAiH;YACjH,uEAAuE;SACxE;QACD,OAAO,EAAE;;;;;;;;;;SAUJ;QACL,UAAU,EAAE;YACV,yGAAyG;YACzG,uEAAuE;YACvE,yGAAyG;SAC1G;KACF;IACD,MAAM,EAAE;QACN,yBAAyB;QACzB,6BAA6B;QAC7B,8CAA8C;KAC/C;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progress-indicator.d.ts","sourceRoot":"","sources":["../../src/rules/progress-indicator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,eAAO,MAAM,iBAAiB,EAAE,IAuC/B,CAAC"}
|