@gemboss/gem-framework 0.18.11 → 0.18.15
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 +38 -0
- package/dist/SOURCE.json +3 -3
- package/dist/editions.js +2 -0
- package/dist/gem-framework.css +36 -7
- package/dist/gem-runtime.js +655 -1
- package/dist/index.js +748 -14
- package/dist/plugins/reviews.d.ts +9 -0
- package/dist/plugins/reviews.js +670 -0
- package/dist/popup-shell.css +4 -4
- package/dist/primitives.css +29 -1
- package/dist/section-gate.js +737 -11
- package/dist/sections.css +2 -2
- package/dist/tokens.css +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -93,6 +93,44 @@ Từ 0.8.2 mỗi module có `.d.ts` cạnh nó (`mount(root?: ParentNode | null,
|
|
|
93
93
|
|
|
94
94
|
## Nhật ký thay đổi
|
|
95
95
|
|
|
96
|
+
- **0.18.15** (20/10/2026): plugin `reviews`, engine danh sách review (GemFactory gap #44). 8 section product-reviews của
|
|
97
|
+
GemFactory mỗi cái mang một bản riêng của cùng một lõi trong behavior.js (14–27 KB mỗi cái); nay lõi đó là MỘT plugin:
|
|
98
|
+
`gem-runtime.js` (load `idle`) hoặc `import { mount } from "@gemboss/gem-framework/plugins/reviews"`. Section xin engine bằng
|
|
99
|
+
`data-rv-root` trên gốc của nó; section không có dấu đó (vẫn mang lõi riêng) không bị gắn, nên lõi riêng và plugin không chạy
|
|
100
|
+
chồng. Hợp đồng chỉ là thuộc tính `data-rv-*` (đầy đủ ở đầu `reviews-engine.ts`):
|
|
101
|
+
- Lõi: sort (menu hoặc select, 13 khoá), lọc sao / có ảnh / chủ đề / quốc gia / tìm (trễ 180 ms) / xoá lọc, trang số (một hay
|
|
102
|
+
nhiều thanh, cửa sổ cố định hoặc `1 2 3 4 … n`) hoặc xem thêm, đếm, đọc thêm, menu, sheet lọc, hữu ích một lần mỗi review
|
|
103
|
+
(`gem:review:vote` trên hub và trên window), lightbox.
|
|
104
|
+
- Chỗ 8 section khác nhau thành thuộc tính: thu gọn N review đầu (`data-rv-collapsed` + `data-rv-expand`), Show N mỗi trang,
|
|
105
|
+
nhãn trang, sao giữ khi bấm lại (`data-rv-star-keep`), chip bộ lọc đang bật, sheet có Apply / Reset, vùng bật tắt và vùng tự
|
|
106
|
+
bỏ lọc khi đóng, dải trượt, tô chữ tìm thấy, chữ số ít (`data-rv-count-one`, `data-rv-status-one`), số theo locale
|
|
107
|
+
(`data-rv-locale`), lightbox (đầu cuối ẩn / mờ / vòng, tập ảnh theo review / nhóm / danh sách JSON của thẻ, bỏ trùng, ảnh kế
|
|
108
|
+
ló ra, vuốt, nền mờ, bỏ phiếu từ trong lightbox hoặc chỉ xem).
|
|
109
|
+
- Khác bản cũ có chủ đích: chọn một mục trong menu thì focus về nút của menu (bản cũ để focus rơi xuống `<body>`); cửa sổ trang
|
|
110
|
+
cố định không còn vẽ dấu … trước trang đầu cửa sổ.
|
|
111
|
+
- Còn ở behavior của từng section: masonry, carousel vòng vô tận + tự chạy, hộp đọc cả review, dịch, sắp xếp hỏi đáp, thẻ chen
|
|
112
|
+
giữa. Chúng vẽ lại theo `gem:reviews:render` (phát trên hub VÀ trên gốc section), và nhờ engine vẽ lại bằng
|
|
113
|
+
`gem:reviews:refresh` trên gốc.
|
|
114
|
+
Đối chiếu trong Chromium trên markup thật của cả 8 section, cùng một chuỗi thao tác (sort, sao, lọc, trang, xem thêm, đọc thêm,
|
|
115
|
+
hữu ích, lightbox, menu; 1280 và 390), behavior.js gốc so với engine: trạng thái trùng từng bước, trừ khác biệt có chủ đích ở trên
|
|
116
|
+
và phần còn ở section.
|
|
117
|
+
- **0.18.14** (20/10/2026): lớp phủ tối là một token (GemFactory gap #17). Khoá màu TUỲ CHỌN `color.scrim` (phát thành
|
|
118
|
+
`--gem-color-scrim`) là màu lớp phủ ở độ đậm tối đa; nền sau dialog popup (55%), lớp tối trên ảnh nền popup (35% → 60%), nền sau
|
|
119
|
+
cart drawer (36%) và lớp tối trên ảnh của hero mặc định (32%) đọc nó qua `gemScrim(N)` = `color-mix(in srgb,
|
|
120
|
+
var(--gem-color-scrim, #000) N%, transparent)`. Không đặt thì ra ĐÚNG như trước (đo Chromium: 5/5 độ đậm trùng từng giá trị
|
|
121
|
+
pixel với màu viết cứng cũ); preset đặt màu có alpha (`rgb(0 0 0 / .7)`) thì mọi lớp phủ nhạt cùng tỉ lệ. Băng dark / accent
|
|
122
|
+
không đảo khoá này. Cảnh báo `untokenized_visual_value` trên một màu đen có alpha giờ chỉ thẳng cách viết bằng token, giữ đúng
|
|
123
|
+
độ đậm.
|
|
124
|
+
- **0.18.13** (20/10/2026): ô nhập, select, textarea có trạng thái hover và lỗi (§9.2; GemFactory Framework › Controls đo cả
|
|
125
|
+
hai là INERT). Hover dày viền thêm 1px theo màu chữ của ô (vòng theo hộp; ô gạch chân và ô tô nền chỉ dày cạnh đáy), chỉ trên
|
|
126
|
+
máy có chuột (`@media (hover: hover)`), không áp cho ô disabled hay ô lỗi. Lỗi (`aria-invalid="true"`, do form đặt) tô viền
|
|
127
|
+
bằng `--gem-color-danger` trộn 70/30 với màu chữ của ô: đạt 3:1 trở lên cả trên ô trắng lẫn ô gạch chân trong băng tối/accent
|
|
128
|
+
(màu danger thuần chỉ 2,4:1 và 1,8:1 ở đó). Áp cho mọi store, có hay không có bộ form.
|
|
129
|
+
- **0.18.12** (20/10/2026): control nền thành một bộ (đo trên GemFactory Framework › Controls). Ô số lượng là một field của
|
|
130
|
+
bộ form: hộp theo chiều cao, viền và góc của bộ (góc tối đa 22px, bộ pill ra ô số lượng tròn), −/+ và con số theo nền và cỡ
|
|
131
|
+
chữ của bộ, shape underline không tô ô (`GEM_FORM_SET_CSS`). Con số nằm giữa ô (`<output>` lệch lên 8–9px). Luật sàn của Dawn
|
|
132
|
+
(`min-height: 4.5rem`) không còn gọi `.gem-input`: trên gốc chữ 16px nó là 72px, ô nhập cao gấp rưỡi select khi không có bộ
|
|
133
|
+
form; `.gem-input` theo sàn của primitive như mọi field.
|
|
96
134
|
- **0.18.11** (19/10/2026): `.gem-stars` nhận sao SVG (gap #45 của GemFactory). Hàng sao rộng đúng bằng các ngôi sao
|
|
97
135
|
(`width: max-content`), và `svg` / `img` trong hàng sao không bị luật nền `max-width: 100%` bóp. Trước đó sao SVG trong
|
|
98
136
|
lớp tô bị co theo bề rộng lớp tô (4,2 vẽ thành năm sao ép), và hàng sao là item bị giãn của grid / flex thì phần trăm tô
|
package/dist/SOURCE.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"package": "@gemboss/gem-framework",
|
|
3
|
-
"version": "0.18.
|
|
4
|
-
"gemtheme_sha": "
|
|
3
|
+
"version": "0.18.15",
|
|
4
|
+
"gemtheme_sha": "998fe4dc3096e9bc0a8e9d39e23b27081138b2c9",
|
|
5
5
|
"gemtheme_dirty": false,
|
|
6
|
-
"framework_version": "0.18.
|
|
6
|
+
"framework_version": "0.18.15"
|
|
7
7
|
}
|
package/dist/editions.js
CHANGED
|
@@ -83,6 +83,8 @@ var GEM_MOTION_SCALE_DEFAULTS = {
|
|
|
83
83
|
blur: "8px"
|
|
84
84
|
};
|
|
85
85
|
var optionalGemTokenKeys = {
|
|
86
|
+
// Lớp phủ tối (GemFactory gap #17): xem GEM_SCRIM_FALLBACK / gemScrim bên dưới.
|
|
87
|
+
color: ["scrim"],
|
|
86
88
|
typography: [...GEM_TYPE_RAMP_KEYS, ...GEM_LINE_HEIGHT_TOKEN_KEYS, ...GEM_BUTTON_TOKEN_KEYS.typography],
|
|
87
89
|
spacing: [...Object.keys(GEM_DERIVED_SPACE_STEPS), ...GEM_PHONE_TOKEN_TARGETS.spacing.map((k) => `${k}Mobile`)],
|
|
88
90
|
layout: GEM_PHONE_TOKEN_TARGETS.layout.map((k) => `${k}Mobile`),
|
package/dist/gem-framework.css
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
--gem-color-success: #008060;
|
|
10
10
|
--gem-color-warning: #9a661a;
|
|
11
11
|
--gem-color-danger: #d72c0d;
|
|
12
|
+
--gem-color-scrim: #000;
|
|
12
13
|
--gem-font-body: Inter, system-ui, sans-serif;
|
|
13
14
|
--gem-font-heading: Inter, system-ui, sans-serif;
|
|
14
15
|
--gem-font-mono: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
@@ -412,6 +413,30 @@ a {
|
|
|
412
413
|
block-size: var(--gem-checkbox-size);
|
|
413
414
|
accent-color: var(--gem-checkbox-accent);
|
|
414
415
|
}
|
|
416
|
+
[data-gem-form-set] :is(.gem-quantity-input) {
|
|
417
|
+
min-height: var(--gem-input-height);
|
|
418
|
+
border: var(--gem-input-border-width) solid var(--gem-input-border-color);
|
|
419
|
+
border-radius: min(var(--gem-input-radius), 22px);
|
|
420
|
+
}
|
|
421
|
+
[data-gem-form-set] :is(.gem-quantity-input__button, .gem-quantity-input__field) {
|
|
422
|
+
background: var(--gem-input-bg);
|
|
423
|
+
font-size: var(--gem-input-font-size);
|
|
424
|
+
}
|
|
425
|
+
[data-gem-form-set][data-gem-field-shape="underline"] :is(.gem-quantity-input__button, .gem-quantity-input__field) {
|
|
426
|
+
background: transparent;
|
|
427
|
+
}
|
|
428
|
+
@media (hover: hover) {
|
|
429
|
+
:is(.gem-input, .gem-select, .gem-textarea, .gem-shell-footer__newsletter .gem-input):where(:not(.gem-search-form .gem-input)):hover:not(:disabled):not([aria-invalid="true"]):not(:focus-visible) {
|
|
430
|
+
border-color: currentColor;
|
|
431
|
+
box-shadow: 0 0 0 1px currentColor;
|
|
432
|
+
}
|
|
433
|
+
[data-gem-form-set]:is([data-gem-field-shape="underline"], [data-gem-field-shape="filled"]) :is(.gem-input, .gem-select, .gem-textarea, .gem-shell-footer__newsletter .gem-input):where(:not(.gem-search-form .gem-input)):hover:not(:disabled):not([aria-invalid="true"]):not(:focus-visible) {
|
|
434
|
+
box-shadow: 0 1px 0 0 currentColor;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
:is(.gem-input, .gem-select, .gem-textarea, .gem-shell-footer__newsletter .gem-input):where(:not(.gem-search-form .gem-input))[aria-invalid="true"] {
|
|
438
|
+
border-color: color-mix(in srgb, var(--gem-color-danger, #b42318) 70%, currentColor);
|
|
439
|
+
}
|
|
415
440
|
.gem-submit {
|
|
416
441
|
cursor: pointer;
|
|
417
442
|
}
|
|
@@ -924,6 +949,10 @@ a {
|
|
|
924
949
|
color: var(--gem-color-text);
|
|
925
950
|
text-align: center;
|
|
926
951
|
}
|
|
952
|
+
.gem-quantity-input__field {
|
|
953
|
+
display: grid;
|
|
954
|
+
place-items: center;
|
|
955
|
+
}
|
|
927
956
|
.gem-quantity-input__button {
|
|
928
957
|
font-weight: 750;
|
|
929
958
|
}
|
|
@@ -1267,7 +1296,7 @@ a {
|
|
|
1267
1296
|
.gem-cart-drawer__overlay {
|
|
1268
1297
|
position: fixed;
|
|
1269
1298
|
inset: 0;
|
|
1270
|
-
background:
|
|
1299
|
+
background: color-mix(in srgb, var(--gem-color-scrim, #000) 36%, transparent);
|
|
1271
1300
|
}
|
|
1272
1301
|
@keyframes gem-cart-drawer-panel-in { from { translate: calc(var(--gem-drawer-offset, 24px) * var(--gem-drawer-dir, 1)) 0; opacity: 0; } }
|
|
1273
1302
|
@keyframes gem-cart-drawer-overlay-in { from { opacity: 0; } }
|
|
@@ -1543,7 +1572,7 @@ a {
|
|
|
1543
1572
|
width: min(880px, 92vw); max-width: none; max-height: min(640px, 92vh); overflow: hidden;
|
|
1544
1573
|
border-radius: var(--gem-radius-lg); box-shadow: var(--gem-shadow-md);
|
|
1545
1574
|
}
|
|
1546
|
-
.gem-popup-shell__dialog::backdrop { background:
|
|
1575
|
+
.gem-popup-shell__dialog::backdrop { background: color-mix(in srgb, var(--gem-color-scrim, #000) 55%, transparent); }
|
|
1547
1576
|
.gem-popup-shell__frame { position: relative; display: grid; grid-template-columns: 1fr 1fr; min-height: 520px; height: 100%; }
|
|
1548
1577
|
.gem-popup-shell__media { position: relative; min-width: 0; overflow: hidden; background: var(--gem-color-surface); }
|
|
1549
1578
|
.gem-popup-shell__image { display: block; width: 100%; height: 100%; object-fit: cover; }
|
|
@@ -1566,7 +1595,7 @@ a {
|
|
|
1566
1595
|
.gem-popup-shell[data-gem-popup-desktop='card-over-image'] .gem-popup-shell__panel {
|
|
1567
1596
|
width: min(420px, 86%); margin: var(--gem-space-xl) 0; background: var(--gem-color-background); border-radius: var(--gem-radius-lg); box-shadow: var(--gem-shadow-sm);
|
|
1568
1597
|
}
|
|
1569
|
-
.gem-popup-shell[data-gem-popup-media='background'] .gem-popup-shell__media::after { content: ''; position: absolute; inset: 0; background: linear-gradient(
|
|
1598
|
+
.gem-popup-shell[data-gem-popup-media='background'] .gem-popup-shell__media::after { content: ''; position: absolute; inset: 0; background: linear-gradient(color-mix(in srgb, var(--gem-color-scrim, #000) 35%, transparent), color-mix(in srgb, var(--gem-color-scrim, #000) 60%, transparent)); }
|
|
1570
1599
|
.gem-popup-shell[data-gem-popup-media='background'] .gem-popup-shell__panel,
|
|
1571
1600
|
.gem-popup-shell[data-gem-popup-media='background'] .gem-popup-shell__close { color: #fff; }
|
|
1572
1601
|
.gem-popup-shell__close {
|
|
@@ -1613,10 +1642,10 @@ a {
|
|
|
1613
1642
|
.gem-popup-shell[data-gem-popup-media='background'] .gem-popup-shell__frame { grid-template-rows: 1fr; }
|
|
1614
1643
|
.gem-popup-shell[data-gem-popup-media='background'] .gem-popup-shell__media { position: absolute; inset: 0; max-height: none; }
|
|
1615
1644
|
}
|
|
1616
|
-
:root:not(:has([data-gem-canvas])) .gem-popup-shell[data-gem-popup-preview='true'] { position: fixed; inset: 0; z-index: 1000; padding: 0; background:
|
|
1645
|
+
:root:not(:has([data-gem-canvas])) .gem-popup-shell[data-gem-popup-preview='true'] { position: fixed; inset: 0; z-index: 1000; padding: 0; background: color-mix(in srgb, var(--gem-color-scrim, #000) 55%, transparent); }
|
|
1617
1646
|
:root:not(:has([data-gem-canvas])) .gem-popup-shell[data-gem-popup-preview='true'] .gem-popup-shell__dialog { position: fixed; inset: 0; display: block; }
|
|
1618
1647
|
:root:has([data-gem-canvas]) .gem-popup-shell[data-gem-popup-preview='true'] .gem-popup-shell__dialog { position: relative; display: block; inset: auto; }
|
|
1619
|
-
:root:has([data-gem-canvas]) .gem-popup-shell[data-gem-popup-preview='true'] { padding: var(--gem-space-xl) var(--gem-layout-gutter); background:
|
|
1648
|
+
:root:has([data-gem-canvas]) .gem-popup-shell[data-gem-popup-preview='true'] { padding: var(--gem-space-xl) var(--gem-layout-gutter); background: color-mix(in srgb, var(--gem-color-scrim, #000) 55%, transparent); }
|
|
1620
1649
|
@media (min-width: 750px) {
|
|
1621
1650
|
:root:has([data-gem-canvas]) .gem-popup-shell[data-gem-popup-preview='true'][data-gem-popup-desktop='fullscreen'] { padding: 0; }
|
|
1622
1651
|
:root:has([data-gem-canvas]) .gem-popup-shell[data-gem-popup-preview='true'][data-gem-popup-desktop='fullscreen'] .gem-popup-shell__dialog { height: 720px; max-height: none; }
|
|
@@ -1793,7 +1822,7 @@ sticky-header.header-wrapper {
|
|
|
1793
1822
|
.newsletter-form__field-wrapper, .field {
|
|
1794
1823
|
position: relative;
|
|
1795
1824
|
}
|
|
1796
|
-
.field__input, .field input
|
|
1825
|
+
.field__input, .field input {
|
|
1797
1826
|
min-height: 4.5rem;
|
|
1798
1827
|
border-radius: var(--inputs-radius, 0);
|
|
1799
1828
|
}
|
|
@@ -2446,7 +2475,7 @@ main > .gem-section:first-child { padding-top: 0; }
|
|
|
2446
2475
|
.gem-hero-banner--default { position: relative; overflow: hidden; padding: 0; color: white; place-items: stretch; }
|
|
2447
2476
|
.gem-hero-banner--default .gem-hero-banner__inner { position: static; width: 100%; min-height: 720px; height: 100%; display: grid; align-items: end; justify-items: center; padding-bottom: 0; }
|
|
2448
2477
|
.gem-hero-banner--default .gem-hero-banner__media { position: absolute; inset: 0; z-index: 0; }
|
|
2449
|
-
.gem-hero-banner--default .gem-hero-banner__media::after { content: ''; position: absolute; inset: 0; background:
|
|
2478
|
+
.gem-hero-banner--default .gem-hero-banner__media::after { content: ''; position: absolute; inset: 0; background: color-mix(in srgb, var(--gem-color-scrim, #000) 32%, transparent); }
|
|
2450
2479
|
.gem-hero-banner--default .gem-hero-banner__image, .gem-hero-banner--default .gem-hero-banner__placeholder { width: 100%; height: 100%; object-fit: cover; display: block; }
|
|
2451
2480
|
.gem-hero-banner--default .gem-hero-banner__copy { position: absolute; z-index: 1; left: 50%; bottom: 50px; transform: translateX(-50%); width: min(702px, 100%); margin: 0; padding: 40px 0; text-align: center; display: block; }
|
|
2452
2481
|
.gem-hero-banner--default .gem-section__heading { margin: 0; font-size: 52px; line-height: 67.6px; color: currentColor; }
|