@gemboss/gem-framework 0.9.0 → 0.9.3

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/README.md CHANGED
@@ -73,6 +73,12 @@ Từ 0.8.2 mỗi module có `.d.ts` cạnh nó (`mount(root?: ParentNode | null,
73
73
 
74
74
  ## Nhật ký thay đổi
75
75
 
76
+ - **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
77
+ 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.
78
+ - **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
79
+ 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
80
+ 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ừ
81
+ `components/revealOnScroll.js` của gemsite, để gemsite dùng được plugin của gói.
76
82
  - **0.9.0** (05/10/2026): `claimIn` (và mọi cổng dùng nó: `fabricatedProofInSource`, làn mã sinh theme của
77
83
  `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
78
84
  một dạng có tên):
package/dist/SOURCE.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "package": "@gemboss/gem-framework",
3
- "version": "0.9.0",
4
- "gemtheme_sha": "a60504b03d89dabdda00812f0b026b5cc68fddfb",
3
+ "version": "0.9.3",
4
+ "gemtheme_sha": "63ccd6e35a160cee1935c6780b4db5deaef86571",
5
5
  "gemtheme_dirty": false,
6
6
  "framework_version": "0.1.0"
7
7
  }
@@ -2466,7 +2466,7 @@ main > .gem-section:first-child { padding-top: 0; }
2466
2466
  .gem-product-card-grid--quick-view-grid .gem-product-card-grid__meta { display: flex; }
2467
2467
  .gem-product-card-grid__controls { display: flex; align-items: center; gap: 20px; min-height: 32px; margin: 0 0 24px; }
2468
2468
  .gem-product-card-grid--quick-view-grid .gem-product-card-grid__controls { min-height: 51px; height: 51px; margin: 0 0 16px !important; padding-top: 10px; }
2469
- .gem-product-card-grid__grid { gap: 8px !important; }
2469
+ .gem-product-card-grid--quick-view-grid .gem-product-card-grid__grid { gap: 8px !important; }
2470
2470
  .gem-product-card-grid__controls .gem-collection-filter-toolbar__filters { display: flex; align-items: center; gap: 18px; border: 0; background: transparent; padding: 0; }
2471
2471
  .gem-product-card-grid__controls .gem-collection-filter-toolbar__filters summary { min-width: auto; border: 0; background: transparent; padding: 0; pointer-events: none; }
2472
2472
  .gem-product-card-grid__controls .gem-collection-filter-toolbar__filter, .gem-product-card-grid__controls .gem-collection-filter-toolbar__sort { display: flex; align-items: center; gap: 8px; font-size: 0.75rem; font-weight: 400; }
@@ -2611,7 +2611,7 @@ main > .gem-section:first-child { padding-top: 0; }
2611
2611
  .gem-hero-banner--compact-collection { padding-block: 25px; }
2612
2612
  .gem-hero-banner--compact-collection .gem-section__heading { font-size: 30px; line-height: 39px; }
2613
2613
  .gem-product-card-grid--quick-view-grid > .gem-section__inner, .gem-main-search > .gem-section__inner { width: calc(100% - 30px); }
2614
- .gem-product-card-grid__grid { gap: 4px !important; }
2614
+ .gem-product-card-grid--quick-view-grid .gem-product-card-grid__grid { gap: 4px !important; }
2615
2615
  .gem-product-card__content { padding-top: 8px; gap: 4px; }
2616
2616
  .gem-product-card__title { font-size: 15px; line-height: 24px; }
2617
2617
  .gem-product-card__price, .gem-product-card__price .gem-price { font-size: 16px; line-height: 24px; }
@@ -847,7 +847,13 @@
847
847
  const nodes = document.querySelectorAll('[data-gem-reveal], .gem-reveal');
848
848
  let bound = 0;
849
849
  const reveal = (node) => { node.dataset.gemRevealState = 'in'; };
850
- if (!target.IntersectionObserver) { nodes.forEach(reveal); api.emit('gem:reveal:ready', { source: 'gem-runtime', count: 0 }); return; }
850
+ // Reduced motion and no IntersectionObserver land on the same answer: show everything now (from gemsite revealOnScroll.js).
851
+ const reduce = typeof target.matchMedia === 'function' && target.matchMedia('(prefers-reduced-motion: reduce)').matches;
852
+ if (reduce || !target.IntersectionObserver) { nodes.forEach(reveal); api.emit('gem:reveal:ready', { source: 'gem-runtime', count: 0 }); return; }
853
+ // Above the fold the browser has already painted the section: writing 'ready' would blink it out and back in.
854
+ // `none` and `default` are the knob's "apply nothing" values; the attribute is still written, so skip them here.
855
+ const off = (node) => { const v = node.getAttribute ? node.getAttribute('data-gem-reveal') : null; return v === 'none' || v === 'default'; };
856
+ const inViewport = (node) => { if (!node.getBoundingClientRect) return true; const r = node.getBoundingClientRect(); const h = target.innerHeight || (document.documentElement && document.documentElement.clientHeight) || 0; return r.top < h && r.bottom > 0; };
851
857
  const observer = new target.IntersectionObserver((entries, obs) => {
852
858
  entries.forEach((entry) => {
853
859
  if (!entry.isIntersecting) return;
@@ -858,6 +864,7 @@
858
864
  }, { threshold: 0.12, rootMargin: '0px 0px -40px 0px' });
859
865
  nodes.forEach((node) => {
860
866
  if (!mark(node, 'reveal-on-scroll')) return;
867
+ if (off(node) || inViewport(node)) { reveal(node); bound += 1; return; }
861
868
  if (!node.dataset.gemRevealState) node.dataset.gemRevealState = 'ready';
862
869
  observer.observe(node);
863
870
  bound += 1;
package/dist/index.js CHANGED
@@ -3292,7 +3292,11 @@ function createDawnParityCss() {
3292
3292
  ".gem-product-card-grid--quick-view-grid .gem-product-card-grid__meta { display: flex; }",
3293
3293
  ".gem-product-card-grid__controls { display: flex; align-items: center; gap: 20px; min-height: 32px; margin: 0 0 24px; }",
3294
3294
  ".gem-product-card-grid--quick-view-grid .gem-product-card-grid__controls { min-height: 51px; height: 51px; margin: 0 0 16px !important; padding-top: 10px; }",
3295
- ".gem-product-card-grid__grid { gap: 8px !important; }",
3295
+ // Scoped to the Dawn quick-view grid it was measured on, as gemsite's copy is (app/globals.css). Unscoped,
3296
+ // it forced an 8px / 4px gap with !important on EVERY section reusing the class: GemFactory's tier-specs
3297
+ // stacked its cards 2-4px apart on mobile (library audit 2026-10-05), and this repo's own
3298
+ // product-card-grid/featured renamed its grid to __cards just to get out from under it (review #628).
3299
+ ".gem-product-card-grid--quick-view-grid .gem-product-card-grid__grid { gap: 8px !important; }",
3296
3300
  ".gem-product-card-grid__controls .gem-collection-filter-toolbar__filters { display: flex; align-items: center; gap: 18px; border: 0; background: transparent; padding: 0; }",
3297
3301
  ".gem-product-card-grid__controls .gem-collection-filter-toolbar__filters summary { min-width: auto; border: 0; background: transparent; padding: 0; pointer-events: none; }",
3298
3302
  ".gem-product-card-grid__controls .gem-collection-filter-toolbar__filter, .gem-product-card-grid__controls .gem-collection-filter-toolbar__sort { display: flex; align-items: center; gap: 8px; font-size: 0.75rem; font-weight: 400; }",
@@ -3445,7 +3449,7 @@ function createDawnParityMobileCss() {
3445
3449
  " .gem-hero-banner--compact-collection { padding-block: 25px; }",
3446
3450
  " .gem-hero-banner--compact-collection .gem-section__heading { font-size: 30px; line-height: 39px; }",
3447
3451
  " .gem-product-card-grid--quick-view-grid > .gem-section__inner, .gem-main-search > .gem-section__inner { width: calc(100% - 30px); }",
3448
- " .gem-product-card-grid__grid { gap: 4px !important; }",
3452
+ " .gem-product-card-grid--quick-view-grid .gem-product-card-grid__grid { gap: 4px !important; }",
3449
3453
  " .gem-product-card__content { padding-top: 8px; gap: 4px; }",
3450
3454
  " .gem-product-card__title { font-size: 15px; line-height: 24px; }",
3451
3455
  " .gem-product-card__price, .gem-product-card__price .gem-price { font-size: 16px; line-height: 24px; }",
@@ -5098,7 +5102,13 @@ var revealOnScrollPluginRegistrationLines = [
5098
5102
  " const nodes = document.querySelectorAll('[data-gem-reveal], .gem-reveal');",
5099
5103
  " let bound = 0;",
5100
5104
  " const reveal = (node) => { node.dataset.gemRevealState = 'in'; };",
5101
- " if (!target.IntersectionObserver) { nodes.forEach(reveal); api.emit('gem:reveal:ready', { source: 'gem-runtime', count: 0 }); return; }",
5105
+ " // Reduced motion and no IntersectionObserver land on the same answer: show everything now (from gemsite revealOnScroll.js).",
5106
+ " const reduce = typeof target.matchMedia === 'function' && target.matchMedia('(prefers-reduced-motion: reduce)').matches;",
5107
+ " if (reduce || !target.IntersectionObserver) { nodes.forEach(reveal); api.emit('gem:reveal:ready', { source: 'gem-runtime', count: 0 }); return; }",
5108
+ " // Above the fold the browser has already painted the section: writing 'ready' would blink it out and back in.",
5109
+ ' // `none` and `default` are the knob\'s "apply nothing" values; the attribute is still written, so skip them here.',
5110
+ " const off = (node) => { const v = node.getAttribute ? node.getAttribute('data-gem-reveal') : null; return v === 'none' || v === 'default'; };",
5111
+ " const inViewport = (node) => { if (!node.getBoundingClientRect) return true; const r = node.getBoundingClientRect(); const h = target.innerHeight || (document.documentElement && document.documentElement.clientHeight) || 0; return r.top < h && r.bottom > 0; };",
5102
5112
  " const observer = new target.IntersectionObserver((entries, obs) => {",
5103
5113
  " entries.forEach((entry) => {",
5104
5114
  " if (!entry.isIntersecting) return;",
@@ -5109,6 +5119,7 @@ var revealOnScrollPluginRegistrationLines = [
5109
5119
  " }, { threshold: 0.12, rootMargin: '0px 0px -40px 0px' });",
5110
5120
  " nodes.forEach((node) => {",
5111
5121
  " if (!mark(node, 'reveal-on-scroll')) return;",
5122
+ " if (off(node) || inViewport(node)) { reveal(node); bound += 1; return; }",
5112
5123
  " if (!node.dataset.gemRevealState) node.dataset.gemRevealState = 'ready';",
5113
5124
  " observer.observe(node);",
5114
5125
  " bound += 1;",
@@ -10,7 +10,13 @@ function install({ document, window, target, mark, canListen, listen: __gemListe
10
10
  const nodes = document.querySelectorAll('[data-gem-reveal], .gem-reveal');
11
11
  let bound = 0;
12
12
  const reveal = (node) => { node.dataset.gemRevealState = 'in'; };
13
- if (!target.IntersectionObserver) { nodes.forEach(reveal); api.emit('gem:reveal:ready', { source: 'gem-runtime', count: 0 }); return; }
13
+ // Reduced motion and no IntersectionObserver land on the same answer: show everything now (from gemsite revealOnScroll.js).
14
+ const reduce = typeof target.matchMedia === 'function' && target.matchMedia('(prefers-reduced-motion: reduce)').matches;
15
+ if (reduce || !target.IntersectionObserver) { nodes.forEach(reveal); api.emit('gem:reveal:ready', { source: 'gem-runtime', count: 0 }); return; }
16
+ // Above the fold the browser has already painted the section: writing 'ready' would blink it out and back in.
17
+ // `none` and `default` are the knob's "apply nothing" values; the attribute is still written, so skip them here.
18
+ const off = (node) => { const v = node.getAttribute ? node.getAttribute('data-gem-reveal') : null; return v === 'none' || v === 'default'; };
19
+ const inViewport = (node) => { if (!node.getBoundingClientRect) return true; const r = node.getBoundingClientRect(); const h = target.innerHeight || (document.documentElement && document.documentElement.clientHeight) || 0; return r.top < h && r.bottom > 0; };
14
20
  const observer = new target.IntersectionObserver((entries, obs) => {
15
21
  entries.forEach((entry) => {
16
22
  if (!entry.isIntersecting) return;
@@ -21,6 +27,7 @@ function install({ document, window, target, mark, canListen, listen: __gemListe
21
27
  }, { threshold: 0.12, rootMargin: '0px 0px -40px 0px' });
22
28
  nodes.forEach((node) => {
23
29
  if (!mark(node, 'reveal-on-scroll')) return;
30
+ if (off(node) || inViewport(node)) { reveal(node); bound += 1; return; }
24
31
  if (!node.dataset.gemRevealState) node.dataset.gemRevealState = 'ready';
25
32
  observer.observe(node);
26
33
  bound += 1;
package/dist/sections.css CHANGED
@@ -878,7 +878,7 @@ main > .gem-section:first-child { padding-top: 0; }
878
878
  .gem-product-card-grid--quick-view-grid .gem-product-card-grid__meta { display: flex; }
879
879
  .gem-product-card-grid__controls { display: flex; align-items: center; gap: 20px; min-height: 32px; margin: 0 0 24px; }
880
880
  .gem-product-card-grid--quick-view-grid .gem-product-card-grid__controls { min-height: 51px; height: 51px; margin: 0 0 16px !important; padding-top: 10px; }
881
- .gem-product-card-grid__grid { gap: 8px !important; }
881
+ .gem-product-card-grid--quick-view-grid .gem-product-card-grid__grid { gap: 8px !important; }
882
882
  .gem-product-card-grid__controls .gem-collection-filter-toolbar__filters { display: flex; align-items: center; gap: 18px; border: 0; background: transparent; padding: 0; }
883
883
  .gem-product-card-grid__controls .gem-collection-filter-toolbar__filters summary { min-width: auto; border: 0; background: transparent; padding: 0; pointer-events: none; }
884
884
  .gem-product-card-grid__controls .gem-collection-filter-toolbar__filter, .gem-product-card-grid__controls .gem-collection-filter-toolbar__sort { display: flex; align-items: center; gap: 8px; font-size: 0.75rem; font-weight: 400; }
@@ -1023,7 +1023,7 @@ main > .gem-section:first-child { padding-top: 0; }
1023
1023
  .gem-hero-banner--compact-collection { padding-block: 25px; }
1024
1024
  .gem-hero-banner--compact-collection .gem-section__heading { font-size: 30px; line-height: 39px; }
1025
1025
  .gem-product-card-grid--quick-view-grid > .gem-section__inner, .gem-main-search > .gem-section__inner { width: calc(100% - 30px); }
1026
- .gem-product-card-grid__grid { gap: 4px !important; }
1026
+ .gem-product-card-grid--quick-view-grid .gem-product-card-grid__grid { gap: 4px !important; }
1027
1027
  .gem-product-card__content { padding-top: 8px; gap: 4px; }
1028
1028
  .gem-product-card__title { font-size: 15px; line-height: 24px; }
1029
1029
  .gem-product-card__price, .gem-product-card__price .gem-price { font-size: 16px; line-height: 24px; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gemboss/gem-framework",
3
- "version": "0.9.0",
3
+ "version": "0.9.3",
4
4
  "description": "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.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",