npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@gemboss/gem-framework

v0.10.1

Published

gem-framework của GemTheme (CSS, runtime, token, bộ kiểm) cộng đúng bộ kiểm section gemtheme dùng khi duyệt. Build từ gemtheme, không sửa ở đây.

Readme

@gemboss/gem-framework

gem-framework của GemTheme đóng thành package, cho các repo ngoài monorepo gemtheme (đầu tiên: gemlabs-gemfactory, tên cũ gemtheme-designlab). Build từ mã nguồn trong repo này; đừng sửa gì ở dist/.

| Cổng vào | Là gì | Nguồn | |---|---|---| | @gemboss/gem-framework | token, createGemThemeCss, runtime, manifest, bộ kiểm framework. Từ 0.3.4 manifest khai họ gem-cart-line-item (khối, __media, __details, __title, __variant, __plan, __meta, __remove, __quantity, __price): framework vốn style và adapter Shopify vốn render nó, nên section dùng markup dòng giỏ của framework không còn bị unknown_gem_class | packages/gem-framework/src | | …/sections | 4 hàm headless.tsx được import (elementOverrides, imageSrcSet, subscriptionPlans, defaultPlan) | packages/gem-sections/src | | …/section-gate | validateSectionArtifacts: ĐÚNG bộ kiểm section gemtheme dùng khi duyệt. Từ 0.3.0 thêm ba cổng của thư viện cho MỘT section: layoutKnobCheck (+ LAYOUT_ATTRS), slotContractDrift (+ slotsReadBy, slotSourceFromElementTree), cssPairingOrphans (+ classesStyledBy, truyền CSS từ createGemThemeCss). Từ 0.3.2 thêm hai cổng pháp lý: fabricatedProofInSource / fabricatedProofInSchema (điểm, số lượt, người, lời hứa bịa) và inventedTestimonyIn (hằng DEMO_*_QUOTE/REVIEW… làm giá trị khi thiếu dữ liệu). Từ 0.3.3 hai cổng này đọc được tiếng Việt ("4,8/5", "đã bán", "miễn phí vận chuyển", "199k", cả chữ NFD), tra giá trị của DEMO.<key> ở mọi chỗ đọc nó (??, \|\|, toán tử ba ngôi, dòng bị Prettier ngắt), và bỏ qua số lượng hiển thị (reviews_to_show…). Nâng từ 0.3.2 lên có thể làm đỏ section trước đó xanh: đó là lời khẳng định nằm trong DEMO. Từ 0.3.5 bắt thêm chữ ký người Việt (tên kèm nơi chốn như "Chị Lan, Hà Nội", hoặc họ + Thị/Văn như "Nguyễn Thị Hoa"; tiêu đề viết hoa từng chữ thì không), điểm sao ("4,9 ★"), rating: 4.9 / reviewCount: "1.284" trong mảng sản phẩm mẫu, và hằng demo ở nhánh else của toán tử ba ngôi (bound ? [] : DEMO_REVIEWS). Mỗi thứ bịa chỉ báo MỘT lần: tại dòng DEMO nếu dòng đó tự lộ, không thì tại chỗ đọc. "đồng hồ" không còn bị đọc là giá. Từ 0.3.6 bắt lời hứa có thời hạn đứng sau từ khoá ("Dùng thử 30 ngày", "Bảo hành 12 tháng", "Nhận trong 2–4 ngày", "Giao 2 giờ") và "hoàn tiền" không kèm số; "Chính sách hoàn tiền" vẫn là nhãn. Từ 0.3.7 câu hỏi (kết thúc bằng "?") không bao giờ là lời hứa, "không hợp lệ"/số bước/nhịp giao không bị báo, và bắt thêm "trong vòng N ngày", "Giao hàng 2–4 ngày", "Bảo hành 1 đổi 1…", "Try it free for 30 days", "Ships in 24h". Từ 0.3.8 xuất thêm claimIn (câu hỏi "một chuỗi này có phải lời khẳng định, người bịa, hay lời hứa?"). Từ 0.3.9 bắt "cancel anytime", "guaranteed delivery", "huỷ bất cứ lúc nào" (chính sách huỷ gói và giao hàng). Từ 0.3.10 lời từ chối ("cannot be canceled", "Không thể hủy") không bị báo, "giao dịch/giao diện" không phải giao hàng, "Delivery not guaranteed" là lời miễn trừ, một chuỗi chỉ gồm con số viết tắt ("199k", "12k+") mang nhãn trung tính "hardcoded figure" (không phân biệt được giá với số đếm), và stringLiteralsIn(line) thay cho hằng STRING_LITERAL (đã gỡ: một regex /g dùng chung rò lastIndex; 0 chỗ dùng ở gemboss/gemfactory/gemsite). Từ 0.3.11 "Huỷ bỏ lọc…" và "Hủy đơn, gọi chúng tôi bất cứ lúc nào" không bị đọc là chính sách huỷ; "huỷ đăng ký" là bỏ nhận tin (như "Unsubscribe anytime"); SOURCE.json ghi gemtheme_dirty, và npm pack từ chối khi ĐẦU VÀO của gói (packages/, gói này trừ package.json, scripts/lib/) có thay đổi chưa commit hoặc git không trả lời được. Từ 0.3.12 bắt lời hứa hoàn tiền không có chữ "hoàn tiền" liền nhau ("nhận lại toàn bộ tiền", "Hoàn lại 100% tiền", "Trả lại tiền nếu không hài lòng"); lời từ chối ("Không được hoàn lại tiền") và tiền thừa/thối khi thanh toán không bị bắt Từ 0.4.0: demoOutsidePreview(tsx) (chữ mẫu DEMO chỉ hiện trong bản xem trước, tức khi section.demo === true; plan xuất bản không bao giờ mang cờ đó) và schema SectionSpec khai trường demo | packages/gem-sections/src/section-artifacts.ts, section-contract.ts | | …/settings-schema | validateSettingsSchema | scripts/lib/settings-schema-contract.mjs | | …/gem-framework.css, …/gem-runtime.js | CSS token mặc định + runtime mọi plugin, dựng sẵn. gem-runtime.js tự chạy khi tải: đăng ký và lên lịch đủ 22 plugin | build | | …/tokens.css, …/primitives.css, …/sections.css, …/popup-shell.css | Từ 0.8.0: gem-framework.css cắt ba (từ 0.8.3 cắt bốn), nối lại theo đúng thứ tự đó thì bằng gem-framework.css từng byte (build dừng nếu không bằng). tokens.css: biến :root + núm style. primitives.css: reset, phần tử nền, tiện ích, mọi primitive .gem-*. sections.css: khung header/footer, lớp section chung, profile theme. popup-shell.css (0.8.3): khung popup .gem-popup-shell, chỉ trang có popup mới cần tải, đặt sau primitives.css và trước sections.css (thứ tự nối: tokens, primitives, popup-shell, sections). CSS riêng của từng section (section-library/**/gem.css) KHÔNG nằm trong gói | createGemThemeCssParts | | …/plugins/<key> (…/plugins/<key>.js), …/runtime-core | Từ 0.8.0: mỗi plugin của runtime là một ES module, export function mount(root = document, options?) trả về unmount(), import không làm gì. Cùng dòng mã với gem-runtime.js (một bảng trong runtime.ts), chỉ khác: mọi x.addEventListener( thành __gemListen(x, để unmount gỡ được. runtime-core.js là phần dùng chung: mountPlugin, createGemApi, gemApi | runtime.ts, runtime-modules.ts, runtime-core.js |

Cài

npm i @gemboss/gem-framework   # npmjs công khai, cùng scope với @gemboss/ui; không cần token

Tới 29/09/2026 gói tên @chriskoh26/gem-framework và chỉ nằm ở GitHub Packages. Registry đó đòi token kể cả khi CÀI, nên build trên Railway không kéo được, và GemFactory phải chép tay file .tgz vào vendor/: nó đứng ở 0.3.2 trong khi gói đã lên 0.4.0 mà không gì báo. Chuyển sang npmjs công khai (Chris chốt scope @gemboss) thì mọi repo cài theo version, và bị tụt thì thấy ngay ở số version. Mã trong gói là CSS và runtime vốn đã tới trình duyệt của người mua, cộng bộ kiểm; license: UNLICENSED giữ nguyên (xem được, không có quyền dùng lại).

Kênh next (thử trước khi phát hành)

Mỗi commit lên main của gemtheme mà đổi gói thì có ngay một bản trên GitHub Packages: @chriskoh26/gem-framework@next, số phiên bản <x.y.z của main>-next.<10 ký tự băm của bản dựng>. Workflow: .github/workflows/gem-framework-next.yml. Kênh latest trên npm vẫn chỉ đi qua passkey (mục dưới).

Thử ở một repo dùng gói, KHÔNG commit hai thay đổi này:

# .npmrc của repo (hoặc ~/.npmrc), token chỉ cần read:packages
@chriskoh26:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_PACKAGES_TOKEN}

npm install --no-save "@gemboss/gem-framework@npm:@chriskoh26/gem-framework@next"

Bí danh giữ nguyên tên @gemboss/gem-framework, nên mã và import của bên dùng không đổi. Bản dựng ghi gemtheme_sha trong dist/SOURCE.json. Luôn ghi @next (hoặc đúng số): tag latest của gói trên GitHub Packages là 0.4.0 từ 29/09/2026, không phải bản mới nhất.

Phát hành

Một lệnh, chạy trên máy, không dùng GitHub Actions (Chris chốt 30/09/2026: không trả tiền runner):

# 1. nâng version trong dist-packages/gem-framework/package.json qua một PR, merge vào main
# 2. rồi, ở bất kỳ đâu trong checkout gemtheme:
bash scripts/publish-gem-framework.sh
DRY_RUN=1 bash scripts/publish-gem-framework.sh   # chạy mọi phép kiểm + npm publish --dry-run, không gửi gì

Script build từ một worktree tạm ở origin/main (không bao giờ từ cây đang sửa), từ chối nếu version đã có trên npm, từ chối nếu dist/SOURCE.json không ghi đúng sha origin/main và gemtheme_dirty: false, tự npm login khi phiên hết hạn, rồi npm publish. npm hỏi mã từ app xác thực của tài khoản gemboss: đó là bước duy nhất phải có người. Đổi luật kiểm (manifest, validation, section-artifacts) là đổi minor: repo dùng package sẽ thấy cảnh báo mới sau khi lên version. Trước khi đổi version, xem npm view @gemboss/gem-framework versions: phiên khác có thể đã lấy số đó.

Plugin module (0.8.0)

import { mount } from "@gemboss/gem-framework/plugins/countdown";
const unmount = mount(sectionEl);   // chỉ gắn trong sectionEl, kể cả chính nó; mặc định cả document
unmount();                          // gỡ listener, timer, IntersectionObserver và dấu data-gem-bound-* nó đặt

Từ 0.8.2 mỗi module có .d.ts cạnh nó (mount(root?: ParentNode | null, options?: MountOptions): Unmount, key, readyEvent); MountOptions, Unmount, GemApi nằm ở @gemboss/gem-framework/runtime-core.

  • Gắn hai lần lên cùng một root thì chỉ gắn một lần; mỗi lần gọi trả một tay cầm, gỡ hết tay cầm thì plugin mới gỡ.
  • options.api: hub sự kiện (truyền window.GemTheme để dùng chung với gem-runtime.js); mặc định một hub chung của các module. Sự kiện gem:* vẫn bắn trên document như runtime.
  • options.window: cửa sổ dùng cho timer/storage/scroll (mặc định root.ownerDocument.defaultView).
  • Trang đã chạy gem-runtime.js rồi mount module lên cùng phần tử thì không gắn đôi: cả hai cùng dùng dấu data-gem-bound-<key>.

Hợp đồng chung với gemsite (0.8.0)

| Plugin | Quyết định | |---|---| | countdown | Ghi cả hai bộ ô: data-gem-countdown-days\|hours\|minutes\|seconds (runtime) và data-gem-cd-days\|hours\|mins\|secs (gemsite, Liquid cũ). Có ô giây thì nhảy mỗi giây, không thì mỗi phút, đúng lúc chữ số phút của thời gian còn lại đổi (từ 0.8.2; trước đó tính từ lúc mount nên chậm tới 59 giây). Lúc hết giờ vẫn đúng tới mili giây. Kết thúc: data-gem-countdown-state="complete" là giá trị chuẩn; nghĩa "ended" của gemsite đi bằng data-gem-countdown-ended="true" trên chính timer (như timer theo thời lượng), trừ khi timer là gốc section (để luật band quyết định). gem:countdown:start báo mỗi phút như cũ với bộ đếm phút, một lần với bộ đếm giây; complete một lần. KHÔNG có mốc giả 3 ngày khi thiếu hạn: gemsite chỉ vẽ timer không hạn trong bản xem trước (CountdownBannerOfferBar.tsx), trên store thật không bao giờ; runtime ghi invalid | | promo-popup | Cùng khoá gem:promo-popup-dismissed:<id>. Đọc cả hai nghĩa: giá trị ở tương lai là "ẩn tới lúc" (runtime ≤ 0.7), giữ ẩn tới lúc đó, và ghi lại MỘT lần thành thời điểm bấm đóng khi trừ đi cửa sổ hiện tại ra một thời điểm đã qua (cửa sổ cũ dài hơn thì giữ nguyên tới khi hết); giá trị ở quá khứ là thời điểm bấm đóng (gemsite), áp cửa sổ data-gem-promo-frequency-days. Ghi từ nay: thời điểm bấm đóng. Hạn "tới lúc" của 0.7 đã qua thì đọc thành thời điểm bấm đóng: popup vắng thêm tối đa một cửa sổ, không bao giờ hiện sớm hơn. Thêm data-gem-promo-trigger = delay (mặc định) | exit_intent (màn cảm ứng rơi về delay) | scroll (data-gem-promo-scroll-percent, 10 tới 90, mặc định 50), mở một lần, ghi data-gem-promo-armed. Trễ mặc định giữ 0 giây của runtime (gemsite: 6) | | sticky-atc | Bar có data-gem-sticky-atc-threshold (gemsite) thì theo luật gemsite: số đó, không thì biến CSS --gem-sticky-atc-threshold, không thì 360. Không có thì data-gem-sticky-threshold như cũ, mặc định 240. Có cả hai: theo của gemsite | | :root muted | #656c79 thay #6b7280 (4,88:1 trên nền #f6f6f3, cũ 4,47:1 dưới ngưỡng AA). Đem từ gemsite | | thanh lọc collection | Không đổi. Bản flex/grid hai khổ của gemsite là gem.css của section collection-filter-toolbar/filter-sort-bar, đã nằm trong section-library của gemtheme, giống từng byte. Gói chỉ mang CSS framework, không mang CSS riêng của section |

Nhật ký thay đổi

  • 0.10.1 (09/10/2026): màu color.warning mặc định #b7791f → #9a661a. Màu cũ chỉ đạt 3,36:1 trên nền mặc định và 3,64:1 trên surface (dưới AA 4,5:1), trong khi section GemFactory dùng nó làm màu chữ và badge vẽ accentText trên nó. Màu mới đạt 4,52 / 4,90, giữ tông. Phiên gemfactory phát hiện khi thêm cảnh báo tương phản cho preset. Test mới default-colours-meet-aa: mọi màu mặc định dùng làm chữ ≥ 4,5:1 trên cả hai nền. Plan khai color.warning riêng (mọi plan sinh từ style pack) thì không đổi: bảng màu pack sửa ở theme-presets (#722). Preview harness của gem-landing-blocks theo màu mới. Vòng tham chiếu chéo nhóm của khoá điện thoại vẫn CHƯA chặn (ghi ở readPhoneTokens).
  • 0.10.0 (08/10/2026, gộp 0.9.10 và 0.9.11 chưa phát hành): phần còn lại của yêu cầu #4 GemFactory (Figma CRO, issue gemfactory #95). Plan không khai khoá nào dưới đây thì CSS tính ra như cũ (mỗi var() lùi về đúng giá trị cũ).
    • Line-height tiêu đề: opt-in data-gem-heading="section" (1.1), .gem-section__heading nền (1.04) và của Dawn parity (1.08) đọc --gem-font-heading-line-height, tức typography.headingLineHeight. Khoá này ĐÃ CÓ trong hai style pack (graphic-editorial 0.95, warm-mineral-spf 1.2) mà trước giờ không tới tiêu đề section: store dùng hai pack đó đổi line-height tiêu đề section và hero theo đúng khoá đã khai. Giá trị không phải line-height bị bỏ (biến khai sai làm var() bỏ qua fallback và rơi về 1,5 của body), validateGemTokens báo invalid_line_height_token. Luật riêng của biến thể Dawn có cỡ px cố định (hero split-proof 46px/1.08, compact-collection…) giữ line-height riêng.
    • Cỡ tiêu đề theo thang chữ, CHỈ khi plan khai typography.base hoặc scale: phát --gem-section-heading-size (= --gem-h2 × núm heading-scale), --gem-hero-heading-size (--gem-h1, chỉ luật hero h1/h2 của Dawn đọc) và bản -mobile (không lớn hơn --gem-heading-phone-cap, trần điện thoại của PROFILE: Dawn khai clamp(2rem, 11vw, 3.6rem) trên :root, profile nền lùi về clamp(1.75rem, 9vw, 2.75rem) như #587). Mọi luật tiêu đề section đọc chúng.
    • Khoá điện thoại: spacing.<bậc>Mobile (cả 10 bậc) và layout.sectionMobile (so khoá bỏ qua hoa thường và dấu nối) khai lại biến gốc trong khối @media (max-width: 749px) của baseMobile. Spacing nhân núm mật độ; giá trị kiểm hình dạng như md (0 trần thành 0px); giá trị không đơn vị, hoặc đọc biến của chính nhóm nó (khai lại trên :root là vòng lặp, padding về 0), bị bỏ và validateGemTokens báo invalid_phone_token. sectionMobile còn đặt --gem-layout-section-mobile trên :root desktop: padding ≤760px của profile nền dùng nguyên giá trị thay vì desktop × 0,72. Không có khoá điện thoại cho page/gutter (bề rộng điện thoại của profile nền không đọc chúng). Ở lane một stylesheet (createGemThemeCss), :root của Dawn đứng sau token và khoá layout.* như trước.
    • Opt-in eyebrow có font-size: var(--gem-text-sm) (mặc định 13,1px, luật nền 13px).
    • Xuất optionalGemTokenKeys (manifest token_groups[].optional_keys đọc từ đây, gồm khoá nút của 0.9.10), gemMobileTokenCssVars, gemPhoneTokenTarget, GEM_HEADING_SIZE_CSS_VARS, GEM_LINE_HEIGHT_TOKEN_KEYS: bản chép ở gemsite (theme-plan-style.ts) và cổng preset của GemFactory đối chiếu với chúng thay vì chép tay.
  • 0.9.11 (08/10/2026): marquee còn MỘT định nghĩa. Trước đó primitives.css có hai: bản của gemtheme #124 (một track nhân đôi con, dịch -50%) nằm TRÊN bản #79 (__viewport + hai track, dịch -100%) nên thua mọi thuộc tính cả hai cùng đặt (min-width, animation), và hợp đồng của #124 chưa từng chạy. Giữ hợp đồng #79, đúng thứ clone kit của gemcapture và GemFactory dựng, cộng những gì của #124 vẫn đang có hiệu lực: viền border-block, will-change, dừng khi rê lên cả .gem-marquee, đảo chiều bằng data-gem-marquee-reverse (bên cạnh .gem-marquee--reverse). Bỏ dòng animation-duration của marquee trong khối reduced-motion của ambient: ở đó track đã animation: none. Đo Chromium (6 kiểu dựng marquee, 390 và 1280, có và không reduced-motion, rê chuột 3 chỗ, đồng hồ animation ghim ở 1234 ms): 516.832 giá trị tính ra, 56 lệch, cả 56 là animation-duration dưới reduced-motion trên track có animation-name: none ở cả hai bản, tức không có gì chạy; bản cố ý hỏng (bỏ will-change và hook đảo chiều bằng thuộc tính) lệch 328. Test mới one-owner-per-selector: selector viết hai lần trong cùng file, cùng @media, có thuộc tính đè nhau thì chỉ được giảm (còn 28 ca, liệt kê trong test).
  • 0.9.10 (08/10/2026): token nút tuỳ chọn (GEM_BUTTON_TOKEN_KEYS, hình dạng ở GEM_BUTTON_TOKEN_SHAPES), cả bốn tên đã có mà chưa ai vẽ: radius.button (--gem-radius-button, scale theo --gem-style-radius; validators và generation-jobs đã dùng tên này), typography.buttonWeight, typography.buttonTransform và typography.buttonLetterSpacing (schema style pack; luxury-editorial khai nút in hoa 0.18em từ trước, giờ mới hiện). Không khai thì nút vẽ y như trước (đo Chromium: 90/90 giá trị tính ra trùng bản cũ ở dawn-parity và ở morph). Bo góc là của riêng nút, nên nút pill không kéo thẻ thành pill; dawn-parity hết ép nút vuông / đậm 400 khi có token. In hoa và giãn chữ không nằm trong .gem-button (UA cho <button> none, còn <a> kế thừa): createGemTokenCss thêm luật :where(...) độ ưu tiên 0 chỉ khi có token (gemButtonCaseCss, export cho storefront tự viết token CSS), nên luật CTA của section vẫn thắng. Nút dạng link không nhận độ đậm / chữ hoa của token. Giá trị sai hình dạng ("pill", rỗng, "semibold") không được phát, validateGemTokens cảnh báo invalid_button_token; khoá snake_case của editor đi qua cùng cổng. Manifest có optional_keys. Nguồn: GemFactory Global Style 08/10/2026 (339 trang store hàng đầu: CTA pill 39%, in hoa 47%, giãn chữ 18%).
  • 0.9.9 (08/10/2026): gemFrameworkVersion (và framework_version / gem_framework_version trong manifest) bằng đúng phiên bản của gói. Từ 0.4.0 tới 0.9.8 nó đứng yên ở "0.1.0", nên trang Framework của gemboss hiện sai phiên bản và GemFactory phải tự đọc phiên bản npm. Test trong index.test.ts đỏ khi hai giá trị lệch nhau. Không đổi CSS hay runtime.
  • 0.9.8 (06/10/2026): biến chỉ được tính là "khai trên :root" khi MỌI vế của selector đúng là gốc (:root, html, :host, có thể kèm điều kiện như :root[data-theme="dark"]), không bao giờ là con của nó. Bản 0.9.7 chỉ xét đầu selector, nên một luật :root .gem-row { --gem-row-auto-sm: … } sẽ biến biến nội bộ thành công khai. Stylesheet hiện tại chưa có luật nào như vậy, nên kết quả không đổi (review của gemboss #3842). Thêm gemPublicCssVariablesFrom(css).
  • 0.9.7 (06/10/2026): validateGemFrameworkCss nhận mọi biến CÔNG KHAI của chính framework, đọc từ stylesheet của nó ở cả hai profile: biến khai trên :root (--gem-card-radius, --gem-media-radius, --gem-ease-soft, --gem-grid-row-gap…) và điểm mở chỉ được đọc kèm dự phòng (--gem-card-background, --gem-marquee-duration…). Trước đó danh sách ghép tay bỏ sót 25 biến như vậy, nên section đọc đúng biến framework vẫn nhận unknown_gem_css_variable (GemFactory gap #29). Biến nội bộ mà framework chỉ khai trên class của nó (--gem-row-auto-*, --gem-stars-*, --gem-section-bg) vẫn bị báo, và tên gõ sai cũng vậy.
  • 0.9.6 (06/10/2026): media-gallery có chế độ ảnh chính + thumbnail (gallery có [data-gem-media-main]): bấm thumbnail thì ảnh chính nhận data-gem-media-src / -alt của nó, bỏ srcset, aria-current chuyển sang thumbnail đó, và phát gem:media:select { index } như behavior.js của section. Phần tử chỉ khớp theo class mà bọc một hook [data-gem-media-gallery] không còn bị gắn thành gallery thứ hai (trước đó nó đánh số lại thumbnail bằng cách đếm mọi <img>, kể cả ảnh chính). Gallery không có ảnh chính chạy như cũ.
  • 0.9.5 (06/10/2026): sticky-atc làm đủ việc của behavior.js section: giá trên thanh đổi theo biến thể khách chọn (data-gem-variant-price trên từng <option>), và form KHÔNG có action (thanh headless) thì chặn submit, phát gem:cart:add với biến thể đang chọn (không phải biến thể đầu ghi trên nút). Form có action (Liquid /cart/add) vẫn để trình duyệt gửi như cũ. Trước đó plugin chỉ báo gem:sticky-atc:submit, nên trang nạp plugin mà không có bản của section thì bấm thêm vào giỏ là tải lại trang.
  • 0.9.4 (06/10/2026): nút tạm dừng của hero-slideshow đổi chữ theo trạng thái như behavior.js của section từng làm: khi dừng nút ghi data-gem-hero-play-label (mặc định Play), khi chạy lại ghi đúng chữ ban đầu của nút (nên nhãn đã dịch không bị đè). Nút có phần tử con (icon) giữ nguyên markup, chỉ đổi aria-pressed. Đây là chỗ lệch cuối cùng giữa plugin và section, để section giao hành vi cho plugin (một chủ, Chris 06/10/2026).
  • 0.9.3 (06/10/2026): CSS Dawn parity chỉ đặt gap !important cho lưới thẻ quick-view (.gem-product-card-grid--quick-view-grid), không cho mọi .gem-product-card-grid__grid. Khớp bản chép của gemsite; store không đổi gì.
  • 0.9.2 (06/10/2026): reveal-on-scroll bỏ qua data-gem-reveal="none" và "default" (hai giá trị "không áp gì" của knob reveal): section hiện ngay, không ẩn chờ cuộn. Trước đó section đặt none vẫn bị ẩn như mọi section reveal.
  • 0.9.1 (06/10/2026): plugin reveal-on-scroll không còn giấu section khách đang thấy. Section đã nằm trong màn hình lúc tải được hiện tại chỗ (trước đó bị đặt ready rồi mới hiện lại, nên phần đầu trang chớp tắt), và khi trình duyệt bật prefers-reduced-motion: reduce mọi section hiện ngay, không ẩn chờ cuộn. Hai luật lấy từ components/revealOnScroll.js của gemsite, để gemsite dùng được plugin của gói.
  • 0.9.0 (05/10/2026): claimIn (và mọi cổng dùng nó: fabricatedProofInSource, làn mã sinh theme của check-fabricated-proof) bắt lời hứa phí ship bằng 0 không có chữ "free" (shippingZeroPromiseIn: tách câu, bỏ ký hiệu đầu dòng, đòi CẢ câu khớp một dạng có tên): "No extra shipping.", "No additional shipping costs", "No shipping fees on this order", "Shipping (costs) included" đứng riêng, "Includes shipping", "Zero shipping fees", "Không mất/thu phí ship", "Không phí vận chuyển", "Đã (bao) gồm phí ship". Chỉ dạng lời hứa không mơ hồ: lời từ chối, câu hỏi, nhãn giỏ ("Total (shipping included)", "Tổng (không tính phí vận chuyển)"), nhãn tuỳ chọn ("Include shipping protection") và trạng thái ("No shipping fees have been configured") vẫn sạch; bộ 130 ca trong section-contract.test.ts. Nguồn: mẫu post-purchase bonus-steps của gemboss in "No extra shipping." cho mọi store (GemFactory gap #21). Minor vì là luật kiểm mới: chữ trước đó xanh có thể đỏ. GemFactory ghim ^0.6.0 nên chỉ có luật này khi nâng phiên bản ở PR riêng.
  • 0.8.3 (05/10/2026): sửa các lỗi popup ghi trong review gemboss PR #3758. Khung popup .gem-popup-shell ra khỏi primitives.css thành popup-shell.css riêng (export ./popup-shell.css): primitives.css nhẹ đi 9.058 byte thô, 1.194 byte gzip; gem-framework.css vẫn đủ luật, khung nằm giữa primitives và sections (đo Chromium 390 và 1280, 15 ca: giống hệt từng điểm ảnh). createPrimitiveCss() không còn khung: ai dựng CSS từ hàm đó mà vẽ popup thì thêm GEM_POPUP_SHELL_CSS. Plugin promo-popup bỏ qua popup đã mang data-gem-bound-promo-popup (popup email-capture tự chạy behavior.js), và api.promoPopup.open chỉ mở popup nó đã gắn, mở cả dialog, tính là lần mở của lượt xem trang (gỡ trigger đang chờ). Countdown chế độ visible bắn gem:countdown:start một lần (trước đây mỗi lần chạy tiếp) và gỡ IntersectionObserver ngay khi hết giờ hoặc dừng.
  • 0.8.2 (05/10/2026): countdown không có ô giây (trang nội dung gemboss chỉ ghi ngày/giờ/phút) đổi chữ số phút đúng lúc thời gian còn lại qua mốc phút, không còn chậm tới 59 giây vì nhịp 60 giây tính từ lúc mount (gemsite #780 tìm ra). Có ô giây thì vẫn mỗi giây; lúc hết giờ vẫn đúng; gem-runtime.js đổi theo vì cùng một bảng. Gói kèm khai báo kiểu: dist/plugins/<key>.d.ts và dist/runtime-core.d.ts, types trong exports của ./plugins/* và ./runtime-core, nên repo TypeScript import @gemboss/gem-framework/plugins/<key> không cần declare module.
  • 0.8.1 (05/10/2026): bỏ .gem-footer khỏi danh sách root của các núm layout (:is(.gem-section, …, .gem-slideshow), 68 chỗ). Không còn gì phát ra class đó từ khi hai footer cũ bị xoá (gemtheme #660, library 1.38.0); hai section đó cũng mang .gem-section nên luật vẫn với tới chúng qua root kia. Không đổi hành vi.
  • 0.8.0 (05/10/2026): plugin module (plugins/*, runtime-core), CSS cắt ba (tokens.css, primitives.css, sections.css), hợp đồng chung countdown / promo-popup / sticky-atc với gemsite, muted #656c79. gem-runtime.js vẫn tự chạy, vẫn đủ 22 plugin; hành vi chỉ đổi ở ba plugin trên, theo bảng trên.