@akinon/pz-theme 2.0.130-rc.0 → 2.0.130
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/CHANGELOG.md +10 -35
- package/package.json +4 -4
- package/src/chrome/__tests__/theme-config-source.test.ts +73 -8
- package/src/chrome/error-composition-source.ts +5 -1
- package/src/chrome/preview-snapshot-source.ts +2 -0
- package/src/chrome/theme-config-source.ts +31 -2
- package/src/load-placeholder-sections.ts +15 -3
- package/src/overlays/use-overlay-breakpoint.ts +4 -2
- package/src/theme-placeholder-wrapper.tsx +49 -7
- package/src/theme-placeholder.tsx +9 -2
- package/src/utils/__tests__/custom-breakpoints.test.ts +326 -0
- package/src/utils/breakpoints.ts +194 -2
- package/src/utils/index.ts +174 -42
- package/src/utils/property-switches.ts +2 -2
- package/src/utils/section-content-width.ts +2 -2
- package/src/utils/visibility-rules.ts +6 -6
package/src/utils/index.ts
CHANGED
|
@@ -23,9 +23,12 @@ import {
|
|
|
23
23
|
import { hasBindingToken } from './iterator-utils';
|
|
24
24
|
import { isCustomThemeType } from '../custom/types';
|
|
25
25
|
import {
|
|
26
|
-
|
|
26
|
+
type CustomBreakpoint,
|
|
27
27
|
MOBILE_MEDIA_QUERY,
|
|
28
|
-
TABLET_MEDIA_QUERY
|
|
28
|
+
TABLET_MEDIA_QUERY,
|
|
29
|
+
baseBreakpointOf,
|
|
30
|
+
customBreakpointMediaQuery,
|
|
31
|
+
fallbackChainOf
|
|
29
32
|
} from './breakpoints';
|
|
30
33
|
import {
|
|
31
34
|
isSectionMaxWidthToken,
|
|
@@ -329,13 +332,11 @@ export const getResponsiveValue = (
|
|
|
329
332
|
// a tablet reads the mobile value before it reads the desktop one, because
|
|
330
333
|
// the mobile rule is the one that covers 768-1023 when no tablet rule was
|
|
331
334
|
// emitted. `desktop` and `mobile` have no intermediate step, so this loop
|
|
332
|
-
// does not run for them and they resolve exactly as they always have.
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
if (inherited !== undefined) return inherited;
|
|
338
|
-
}
|
|
335
|
+
// does not run for them and they resolve exactly as they always have. A
|
|
336
|
+
// custom breakpoint reads the built-in one it stands on.
|
|
337
|
+
for (const next of fallbackChainOf(breakpoint)) {
|
|
338
|
+
const inherited = responsiveValue[next];
|
|
339
|
+
if (inherited !== undefined) return inherited;
|
|
339
340
|
}
|
|
340
341
|
|
|
341
342
|
if (responsiveValue.desktop !== undefined) return responsiveValue.desktop;
|
|
@@ -851,17 +852,15 @@ const isAuthored = (value: unknown): value is string | number =>
|
|
|
851
852
|
*/
|
|
852
853
|
const resolveEntryValue = (
|
|
853
854
|
entry: ResponsiveEntry,
|
|
854
|
-
breakpoint: string
|
|
855
|
+
breakpoint: string,
|
|
856
|
+
customBreakpoints?: CustomBreakpoint[]
|
|
855
857
|
): string | number | undefined => {
|
|
856
858
|
const own = entry[breakpoint as keyof ResponsiveEntry];
|
|
857
859
|
if (own !== undefined) return own;
|
|
858
860
|
|
|
859
|
-
const
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
const inherited = entry[next as keyof ResponsiveEntry];
|
|
863
|
-
if (inherited !== undefined) return inherited;
|
|
864
|
-
}
|
|
861
|
+
for (const next of fallbackChainOf(breakpoint, customBreakpoints)) {
|
|
862
|
+
const inherited = entry[next as keyof ResponsiveEntry];
|
|
863
|
+
if (inherited !== undefined) return inherited;
|
|
865
864
|
}
|
|
866
865
|
|
|
867
866
|
return entry.desktop;
|
|
@@ -974,14 +973,31 @@ const formatCSSValue = (property: string, value: string | number): string => {
|
|
|
974
973
|
return String(value);
|
|
975
974
|
};
|
|
976
975
|
|
|
976
|
+
/** The helper keys the hover rules are built from. */
|
|
977
|
+
const HOVER_HELPER_KEYS = [
|
|
978
|
+
'hover-color',
|
|
979
|
+
'hover-opacity',
|
|
980
|
+
'hover-flex',
|
|
981
|
+
'hover-child-flex'
|
|
982
|
+
];
|
|
983
|
+
|
|
977
984
|
const generateElementCSS = (
|
|
978
985
|
selector: string,
|
|
979
986
|
rawStyles: ResponsiveStyles,
|
|
980
987
|
targetBreakpoint?: string,
|
|
981
|
-
options?: {
|
|
988
|
+
options?: {
|
|
989
|
+
treatHelperKeysAsCss?: boolean;
|
|
990
|
+
/**
|
|
991
|
+
* The theme's custom breakpoints. Passed in rather than read from the
|
|
992
|
+
* browser registry because the live stylesheet is built on the server.
|
|
993
|
+
*/
|
|
994
|
+
customBreakpoints?: CustomBreakpoint[];
|
|
995
|
+
}
|
|
982
996
|
): string => {
|
|
983
997
|
if (!rawStyles || Object.keys(rawStyles).length === 0) return '';
|
|
984
998
|
|
|
999
|
+
const customBreakpoints = options?.customBreakpoints ?? [];
|
|
1000
|
+
|
|
985
1001
|
// Bound values belong to the per-row resolution, not to the shared rule.
|
|
986
1002
|
const styles = stripBoundStyleValues(
|
|
987
1003
|
rawStyles as Record<string, unknown>
|
|
@@ -997,22 +1013,41 @@ const generateElementCSS = (
|
|
|
997
1013
|
return styles[kebabKey] ?? styles[camelKey];
|
|
998
1014
|
};
|
|
999
1015
|
|
|
1016
|
+
// `getResponsiveValue` with this theme's custom breakpoints in view: their own
|
|
1017
|
+
// value, and otherwise whatever the built-in breakpoint they stand on reads.
|
|
1018
|
+
const valueAt = (
|
|
1019
|
+
entry: unknown,
|
|
1020
|
+
breakpoint: string,
|
|
1021
|
+
fallback: unknown
|
|
1022
|
+
): unknown => {
|
|
1023
|
+
const custom = customBreakpoints.find((bp) => bp.name === breakpoint);
|
|
1024
|
+
|
|
1025
|
+
if (custom && entry && typeof entry === 'object' && !Array.isArray(entry)) {
|
|
1026
|
+
const own = (entry as Record<string, unknown>)[breakpoint];
|
|
1027
|
+
if (own !== undefined) return own;
|
|
1028
|
+
|
|
1029
|
+
return getResponsiveValue(entry, baseBreakpointOf(custom), fallback);
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
return getResponsiveValue(entry, breakpoint, fallback);
|
|
1033
|
+
};
|
|
1034
|
+
|
|
1000
1035
|
const getBackgroundAlpha = (breakpoint: string): number | null => {
|
|
1001
1036
|
const entry = getStyleEntry('background-opacity');
|
|
1002
|
-
const value = entry ?
|
|
1037
|
+
const value = entry ? valueAt(entry, breakpoint, '100') : '100';
|
|
1003
1038
|
return clampAlpha(value, 100);
|
|
1004
1039
|
};
|
|
1005
1040
|
|
|
1006
1041
|
const getHoverAlpha = (breakpoint: string): number | null => {
|
|
1007
1042
|
const entry = getStyleEntry('hover-opacity');
|
|
1008
|
-
const value = entry ?
|
|
1043
|
+
const value = entry ? valueAt(entry, breakpoint, '100') : '100';
|
|
1009
1044
|
return clampAlpha(value, 100);
|
|
1010
1045
|
};
|
|
1011
1046
|
|
|
1012
1047
|
const getHoverColor = (breakpoint: string): string | null => {
|
|
1013
1048
|
const entry = getStyleEntry('hover-color');
|
|
1014
1049
|
const value = entry
|
|
1015
|
-
?
|
|
1050
|
+
? valueAt(entry, breakpoint, 'var(--theme-secondary)')
|
|
1016
1051
|
: undefined;
|
|
1017
1052
|
if (value === undefined || value === null || value === '') return null;
|
|
1018
1053
|
return String(value);
|
|
@@ -1021,7 +1056,7 @@ const generateElementCSS = (
|
|
|
1021
1056
|
const getHoverFlex = (breakpoint: string): string | null => {
|
|
1022
1057
|
const entry = getStyleEntry('hover-flex');
|
|
1023
1058
|
const value = entry
|
|
1024
|
-
?
|
|
1059
|
+
? valueAt(entry, breakpoint, undefined)
|
|
1025
1060
|
: undefined;
|
|
1026
1061
|
if (value === undefined || value === null || value === '') return null;
|
|
1027
1062
|
return String(value);
|
|
@@ -1030,7 +1065,7 @@ const generateElementCSS = (
|
|
|
1030
1065
|
const getHoverChildFlex = (breakpoint: string): string | null => {
|
|
1031
1066
|
const entry = getStyleEntry('hover-child-flex');
|
|
1032
1067
|
const value = entry
|
|
1033
|
-
?
|
|
1068
|
+
? valueAt(entry, breakpoint, undefined)
|
|
1034
1069
|
: undefined;
|
|
1035
1070
|
if (value === undefined || value === null || value === '') return null;
|
|
1036
1071
|
return String(value);
|
|
@@ -1120,7 +1155,8 @@ const generateElementCSS = (
|
|
|
1120
1155
|
// canvas show a tablet the device never renders.
|
|
1121
1156
|
const breakpointValue = resolveEntryValue(
|
|
1122
1157
|
responsiveValue,
|
|
1123
|
-
targetBreakpoint
|
|
1158
|
+
targetBreakpoint,
|
|
1159
|
+
customBreakpoints
|
|
1124
1160
|
);
|
|
1125
1161
|
if (
|
|
1126
1162
|
breakpointValue !== undefined &&
|
|
@@ -1230,6 +1266,9 @@ const generateElementCSS = (
|
|
|
1230
1266
|
const desktopStyles: string[] = [];
|
|
1231
1267
|
const mobileStyles: string[] = [];
|
|
1232
1268
|
const tabletStyles: string[] = [];
|
|
1269
|
+
const customStyles = new Map<string, string[]>(
|
|
1270
|
+
customBreakpoints.map((bp) => [bp.name, []])
|
|
1271
|
+
);
|
|
1233
1272
|
|
|
1234
1273
|
/**
|
|
1235
1274
|
* The declaration value one breakpoint would produce for one property, by
|
|
@@ -1405,6 +1444,23 @@ const generateElementCSS = (
|
|
|
1405
1444
|
tabletStyles.push(` ${cssProperty}: ${formattedTablet}`);
|
|
1406
1445
|
}
|
|
1407
1446
|
}
|
|
1447
|
+
|
|
1448
|
+
// A custom breakpoint writes only what it sets itself; everything else
|
|
1449
|
+
// in its range is already painted by the rules above.
|
|
1450
|
+
customBreakpoints.forEach((bp) => {
|
|
1451
|
+
const own = (responsiveValue as Record<string, unknown>)[bp.name];
|
|
1452
|
+
if (!isAuthored(own)) return;
|
|
1453
|
+
|
|
1454
|
+
const formatted = declarationValue(
|
|
1455
|
+
property,
|
|
1456
|
+
cssProperty,
|
|
1457
|
+
bp.name,
|
|
1458
|
+
own
|
|
1459
|
+
);
|
|
1460
|
+
if (formatted) {
|
|
1461
|
+
customStyles.get(bp.name)?.push(` ${cssProperty}: ${formatted}`);
|
|
1462
|
+
}
|
|
1463
|
+
});
|
|
1408
1464
|
} else {
|
|
1409
1465
|
if (cssProperty === 'background-color' && typeof value === 'string') {
|
|
1410
1466
|
const backgroundAlpha = getBackgroundAlpha('desktop');
|
|
@@ -1463,6 +1519,32 @@ const generateElementCSS = (
|
|
|
1463
1519
|
css += `${TABLET_MEDIA_QUERY} {\n${tabletDeclarations}${tabletHoverCss}}\n`;
|
|
1464
1520
|
}
|
|
1465
1521
|
|
|
1522
|
+
// Last of all: a custom range overrides whichever built-in rules match inside
|
|
1523
|
+
// it, and at equal specificity it is source order that lets it. Nothing is
|
|
1524
|
+
// written for a theme without custom breakpoints, so its stylesheet is the
|
|
1525
|
+
// one it always was.
|
|
1526
|
+
customBreakpoints.forEach((bp) => {
|
|
1527
|
+
const declarations = customStyles.get(bp.name) ?? [];
|
|
1528
|
+
const setsHover = HOVER_HELPER_KEYS.some((key) => {
|
|
1529
|
+
const entry = getStyleEntry(key);
|
|
1530
|
+
return (
|
|
1531
|
+
!!entry &&
|
|
1532
|
+
typeof entry === 'object' &&
|
|
1533
|
+
isAuthored((entry as Record<string, unknown>)[bp.name])
|
|
1534
|
+
);
|
|
1535
|
+
});
|
|
1536
|
+
const hoverCss = setsHover ? buildHoverCss(bp.name, ' ') : '';
|
|
1537
|
+
|
|
1538
|
+
if (declarations.length === 0 && !hoverCss) return;
|
|
1539
|
+
|
|
1540
|
+
const rule =
|
|
1541
|
+
declarations.length > 0
|
|
1542
|
+
? ` ${selector} {\n ${declarations.join(';\n ')};\n }\n`
|
|
1543
|
+
: '';
|
|
1544
|
+
|
|
1545
|
+
css += `${customBreakpointMediaQuery(bp)} {\n${rule}${hoverCss}}\n`;
|
|
1546
|
+
});
|
|
1547
|
+
|
|
1466
1548
|
return css;
|
|
1467
1549
|
};
|
|
1468
1550
|
|
|
@@ -1477,7 +1559,8 @@ const generateElementCSS = (
|
|
|
1477
1559
|
export const generatePartCSS = (
|
|
1478
1560
|
blockSelector: string,
|
|
1479
1561
|
styles: Record<string, unknown>,
|
|
1480
|
-
targetBreakpoint?: string
|
|
1562
|
+
targetBreakpoint?: string,
|
|
1563
|
+
customBreakpoints?: CustomBreakpoint[]
|
|
1481
1564
|
): string => {
|
|
1482
1565
|
const { parts } = splitPartStyles(styles);
|
|
1483
1566
|
if (parts.length === 0) return '';
|
|
@@ -1492,7 +1575,7 @@ export const generatePartCSS = (
|
|
|
1492
1575
|
selectors.join(',\n'),
|
|
1493
1576
|
bucket.styles as ResponsiveStyles,
|
|
1494
1577
|
targetBreakpoint,
|
|
1495
|
-
{ treatHelperKeysAsCss: true }
|
|
1578
|
+
{ treatHelperKeysAsCss: true, customBreakpoints }
|
|
1496
1579
|
);
|
|
1497
1580
|
|
|
1498
1581
|
if (!rules) return;
|
|
@@ -1540,7 +1623,8 @@ const generateRootStateCSS = (
|
|
|
1540
1623
|
* stateless rule does — and the guard has to be placed per state expression,
|
|
1541
1624
|
* which is why the flag travels here instead of a finished selector.
|
|
1542
1625
|
*/
|
|
1543
|
-
targetsInnerRoot = false
|
|
1626
|
+
targetsInnerRoot = false,
|
|
1627
|
+
customBreakpoints?: CustomBreakpoint[]
|
|
1544
1628
|
): string => {
|
|
1545
1629
|
const { rootStates } = splitPartStyles(styles);
|
|
1546
1630
|
if (rootStates.length === 0) return '';
|
|
@@ -1562,7 +1646,7 @@ const generateRootStateCSS = (
|
|
|
1562
1646
|
// `:<state>/opacity` the editor offers is dropped on the floor. A state
|
|
1563
1647
|
// BUCKET has no such helper: there it is a real CSS property, exactly as
|
|
1564
1648
|
// it is on a part, which is why `generatePartCSS` has always passed this.
|
|
1565
|
-
{ treatHelperKeysAsCss: true }
|
|
1649
|
+
{ treatHelperKeysAsCss: true, customBreakpoints }
|
|
1566
1650
|
);
|
|
1567
1651
|
|
|
1568
1652
|
if (!rules) return;
|
|
@@ -1581,11 +1665,28 @@ const generateRootStateCSS = (
|
|
|
1581
1665
|
return css;
|
|
1582
1666
|
};
|
|
1583
1667
|
|
|
1668
|
+
/**
|
|
1669
|
+
* The canvas target as one of the three built-in breakpoints, for the emitters
|
|
1670
|
+
* that know only those: a custom breakpoint becomes the band it stands on.
|
|
1671
|
+
*/
|
|
1672
|
+
const builtInTargetOf = (
|
|
1673
|
+
targetBreakpoint: string | undefined,
|
|
1674
|
+
customBreakpoints: CustomBreakpoint[]
|
|
1675
|
+
): string | undefined => {
|
|
1676
|
+
const custom = targetBreakpoint
|
|
1677
|
+
? customBreakpoints.find((bp) => bp.name === targetBreakpoint)
|
|
1678
|
+
: undefined;
|
|
1679
|
+
|
|
1680
|
+
return custom ? baseBreakpointOf(custom) : targetBreakpoint;
|
|
1681
|
+
};
|
|
1682
|
+
|
|
1584
1683
|
const collectBlockCSS = (
|
|
1585
1684
|
blocks: Block[],
|
|
1586
|
-
targetBreakpoint?: string
|
|
1685
|
+
targetBreakpoint?: string,
|
|
1686
|
+
customBreakpoints: CustomBreakpoint[] = []
|
|
1587
1687
|
): string => {
|
|
1588
1688
|
let css = '';
|
|
1689
|
+
const hatchBreakpoint = builtInTargetOf(targetBreakpoint, customBreakpoints);
|
|
1589
1690
|
|
|
1590
1691
|
blocks.forEach((block) => {
|
|
1591
1692
|
// A block that IS or CONTAINS the checkout flow outlet has the real
|
|
@@ -1630,7 +1731,8 @@ const collectBlockCSS = (
|
|
|
1630
1731
|
css += generateElementCSS(
|
|
1631
1732
|
rootSelectors.join(',\n'),
|
|
1632
1733
|
root,
|
|
1633
|
-
targetBreakpoint
|
|
1734
|
+
targetBreakpoint,
|
|
1735
|
+
{ customBreakpoints }
|
|
1634
1736
|
);
|
|
1635
1737
|
}
|
|
1636
1738
|
|
|
@@ -1640,10 +1742,16 @@ const collectBlockCSS = (
|
|
|
1640
1742
|
selector,
|
|
1641
1743
|
blockStyles,
|
|
1642
1744
|
targetBreakpoint,
|
|
1643
|
-
targetsInnerRoot
|
|
1745
|
+
targetsInnerRoot,
|
|
1746
|
+
customBreakpoints
|
|
1644
1747
|
);
|
|
1645
1748
|
|
|
1646
|
-
css += generatePartCSS(
|
|
1749
|
+
css += generatePartCSS(
|
|
1750
|
+
selector,
|
|
1751
|
+
blockStyles,
|
|
1752
|
+
targetBreakpoint,
|
|
1753
|
+
customBreakpoints
|
|
1754
|
+
);
|
|
1647
1755
|
}
|
|
1648
1756
|
|
|
1649
1757
|
if (block.properties) {
|
|
@@ -1653,7 +1761,7 @@ const collectBlockCSS = (
|
|
|
1653
1761
|
const customCss = buildCustomCss(
|
|
1654
1762
|
block.properties as Record<string, unknown>,
|
|
1655
1763
|
selector,
|
|
1656
|
-
|
|
1764
|
+
hatchBreakpoint
|
|
1657
1765
|
);
|
|
1658
1766
|
|
|
1659
1767
|
css += guardsCheckoutFlow ? stripHidingCustomCss(customCss) : customCss;
|
|
@@ -1664,7 +1772,7 @@ const collectBlockCSS = (
|
|
|
1664
1772
|
const partCustomCss = buildPartCustomCss(
|
|
1665
1773
|
block.properties as Record<string, unknown>,
|
|
1666
1774
|
selector,
|
|
1667
|
-
|
|
1775
|
+
hatchBreakpoint
|
|
1668
1776
|
);
|
|
1669
1777
|
|
|
1670
1778
|
css += guardsCheckoutFlow
|
|
@@ -1673,7 +1781,11 @@ const collectBlockCSS = (
|
|
|
1673
1781
|
}
|
|
1674
1782
|
|
|
1675
1783
|
if (block.blocks && block.blocks.length > 0) {
|
|
1676
|
-
css += collectBlockCSS(
|
|
1784
|
+
css += collectBlockCSS(
|
|
1785
|
+
block.blocks,
|
|
1786
|
+
targetBreakpoint,
|
|
1787
|
+
customBreakpoints
|
|
1788
|
+
);
|
|
1677
1789
|
}
|
|
1678
1790
|
});
|
|
1679
1791
|
|
|
@@ -1682,15 +1794,22 @@ const collectBlockCSS = (
|
|
|
1682
1794
|
|
|
1683
1795
|
export const generateThemeCSS = (
|
|
1684
1796
|
sections: Section[],
|
|
1685
|
-
targetBreakpoint?: string
|
|
1797
|
+
targetBreakpoint?: string,
|
|
1798
|
+
/** The theme's custom breakpoints (`readCustomBreakpoints`). */
|
|
1799
|
+
customBreakpoints: CustomBreakpoint[] = []
|
|
1686
1800
|
): string => {
|
|
1801
|
+
// The custom-CSS hatch and the scoped line breaks know the three built-in
|
|
1802
|
+
// bands only. On the canvas a custom breakpoint shows them as the band it
|
|
1803
|
+
// stands on does, which is also what its range shows on the live site.
|
|
1804
|
+
const hatchBreakpoint = builtInTargetOf(targetBreakpoint, customBreakpoints);
|
|
1805
|
+
|
|
1687
1806
|
// First, and outside every section selector: the rules are global by nature
|
|
1688
1807
|
// (a `<br>` scoped to the phone means the same thing wherever it was typed),
|
|
1689
1808
|
// and they must lose a specificity tie to anything a section or block emits
|
|
1690
1809
|
// for itself, which source order settles. Emitted only when the composition
|
|
1691
1810
|
// actually carries a scoped break — see utils/line-breaks.ts.
|
|
1692
1811
|
let css = compositionUsesScopedLineBreaks(sections)
|
|
1693
|
-
? buildLineBreakCss(
|
|
1812
|
+
? buildLineBreakCss(hatchBreakpoint)
|
|
1694
1813
|
: '';
|
|
1695
1814
|
|
|
1696
1815
|
sections.forEach((section) => {
|
|
@@ -1745,7 +1864,8 @@ export const generateThemeCSS = (
|
|
|
1745
1864
|
css += generateElementCSS(
|
|
1746
1865
|
sectionSelector,
|
|
1747
1866
|
resolvesOwnMaxWidth ? band : resolveSectionMaxWidthTokens(band),
|
|
1748
|
-
targetBreakpoint
|
|
1867
|
+
targetBreakpoint,
|
|
1868
|
+
{ customBreakpoints }
|
|
1749
1869
|
);
|
|
1750
1870
|
}
|
|
1751
1871
|
|
|
@@ -1757,7 +1877,8 @@ export const generateThemeCSS = (
|
|
|
1757
1877
|
css += generateElementCSS(
|
|
1758
1878
|
`${sectionSelector} > [${SECTION_CONTENT_ATTRIBUTE}]`,
|
|
1759
1879
|
content as ResponsiveStyles,
|
|
1760
|
-
targetBreakpoint
|
|
1880
|
+
targetBreakpoint,
|
|
1881
|
+
{ customBreakpoints }
|
|
1761
1882
|
);
|
|
1762
1883
|
}
|
|
1763
1884
|
}
|
|
@@ -1765,10 +1886,17 @@ export const generateThemeCSS = (
|
|
|
1765
1886
|
css += generateRootStateCSS(
|
|
1766
1887
|
sectionSelector,
|
|
1767
1888
|
sectionStyles,
|
|
1768
|
-
targetBreakpoint
|
|
1889
|
+
targetBreakpoint,
|
|
1890
|
+
false,
|
|
1891
|
+
customBreakpoints
|
|
1769
1892
|
);
|
|
1770
1893
|
|
|
1771
|
-
css += generatePartCSS(
|
|
1894
|
+
css += generatePartCSS(
|
|
1895
|
+
sectionSelector,
|
|
1896
|
+
sectionStyles,
|
|
1897
|
+
targetBreakpoint,
|
|
1898
|
+
customBreakpoints
|
|
1899
|
+
);
|
|
1772
1900
|
}
|
|
1773
1901
|
|
|
1774
1902
|
if (section.properties) {
|
|
@@ -1778,14 +1906,18 @@ export const generateThemeCSS = (
|
|
|
1778
1906
|
const customCss = buildCustomCss(
|
|
1779
1907
|
section.properties as Record<string, unknown>,
|
|
1780
1908
|
sectionSelector,
|
|
1781
|
-
|
|
1909
|
+
hatchBreakpoint
|
|
1782
1910
|
);
|
|
1783
1911
|
|
|
1784
1912
|
css += guardsCheckoutFlow ? stripHidingCustomCss(customCss) : customCss;
|
|
1785
1913
|
}
|
|
1786
1914
|
|
|
1787
1915
|
if (section.blocks && section.blocks.length > 0) {
|
|
1788
|
-
css += collectBlockCSS(
|
|
1916
|
+
css += collectBlockCSS(
|
|
1917
|
+
section.blocks,
|
|
1918
|
+
targetBreakpoint,
|
|
1919
|
+
customBreakpoints
|
|
1920
|
+
);
|
|
1789
1921
|
}
|
|
1790
1922
|
});
|
|
1791
1923
|
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
|
|
42
42
|
import type { Block } from '../theme-block';
|
|
43
43
|
import type { Section } from '../theme-section';
|
|
44
|
-
import {
|
|
44
|
+
import { fallbackChainOf } from './breakpoints';
|
|
45
45
|
|
|
46
46
|
export const VISIBLE_WHEN_PROPERTY = 'visibleWhenProperty';
|
|
47
47
|
export const HOVER_REVEAL_WHEN_PROPERTY = 'hoverRevealWhenProperty';
|
|
@@ -95,7 +95,7 @@ const readResponsive = (value: unknown, breakpoint: string): unknown => {
|
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
const record = value as Properties;
|
|
98
|
-
const chain = [breakpoint, ...(
|
|
98
|
+
const chain = [breakpoint, ...fallbackChainOf(breakpoint), 'desktop'];
|
|
99
99
|
|
|
100
100
|
for (const key of chain) {
|
|
101
101
|
if (record[key] !== undefined) return record[key];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BREAKPOINTS,
|
|
1
|
+
import { BREAKPOINTS, fallbackChainOf } from './breakpoints';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* How wide the CONTENT of a band is allowed to get, as opposed to how wide the
|
|
@@ -73,7 +73,7 @@ const at = (value: unknown, breakpoint: string): unknown => {
|
|
|
73
73
|
const own = value[breakpoint];
|
|
74
74
|
if (own !== undefined) return own;
|
|
75
75
|
|
|
76
|
-
for (const next of
|
|
76
|
+
for (const next of fallbackChainOf(breakpoint)) {
|
|
77
77
|
if (value[next] !== undefined) return value[next];
|
|
78
78
|
}
|
|
79
79
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Block } from '../theme-block';
|
|
2
2
|
import { Section } from '../theme-section';
|
|
3
|
-
import {
|
|
3
|
+
import { fallbackChainOf } from './breakpoints';
|
|
4
4
|
import { containsCheckoutOutlet } from './checkout-safety';
|
|
5
5
|
import { devWarn } from './dev-warn';
|
|
6
6
|
|
|
@@ -87,10 +87,10 @@ export const isBreakpointAllowed = (
|
|
|
87
87
|
): boolean => {
|
|
88
88
|
if (allowed.includes(breakpoint)) return true;
|
|
89
89
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
return
|
|
90
|
+
// A custom breakpoint the list does not name answers as the built-in one it
|
|
91
|
+
// stands on, the way an unticked-because-it-did-not-exist tablet answers as
|
|
92
|
+
// mobile: adding a breakpoint must not hide what was already showing there.
|
|
93
|
+
return fallbackChainOf(breakpoint).some((next) => allowed.includes(next));
|
|
94
94
|
};
|
|
95
95
|
|
|
96
96
|
export interface VisibilityRuleContext {
|
|
@@ -548,7 +548,7 @@ const readResponsive = (value: unknown, breakpoint?: string): unknown => {
|
|
|
548
548
|
const record = value as Record<string, unknown>;
|
|
549
549
|
const chain = [
|
|
550
550
|
breakpoint,
|
|
551
|
-
...(breakpoint ?
|
|
551
|
+
...(breakpoint ? fallbackChainOf(breakpoint) : []),
|
|
552
552
|
'desktop'
|
|
553
553
|
];
|
|
554
554
|
|