emily-css 1.0.27 → 1.0.28
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 +8 -0
- package/package.json +1 -1
- package/src/generators.js +12 -2
- package/src/index.js +130 -6
- package/src/purge.js +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,14 @@ All notable changes to `emily-css` are documented here.
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## v1.0.28 — May 2026
|
|
8
|
+
|
|
9
|
+
**added new utilities**
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
- added new utilties and tests
|
|
13
|
+
|
|
14
|
+
---
|
|
7
15
|
## v1.0.27 — May 2026
|
|
8
16
|
|
|
9
17
|
**colour system redesign — brand/accent tokens + semantic colours (v1.0.23)**
|
package/package.json
CHANGED
package/src/generators.js
CHANGED
|
@@ -424,6 +424,12 @@ function svgUtilities(colours) {
|
|
|
424
424
|
|
|
425
425
|
css += `.fill-current { fill: currentColor; }\n`;
|
|
426
426
|
css += `.stroke-current { stroke: currentColor; }\n`;
|
|
427
|
+
css += `.fill-white { fill: #FAFAFA; }\n`;
|
|
428
|
+
css += `.fill-black { fill: #111110; }\n`;
|
|
429
|
+
css += `.fill-transparent { fill: transparent; }\n`;
|
|
430
|
+
css += `.stroke-white { stroke: #FAFAFA; }\n`;
|
|
431
|
+
css += `.stroke-black { stroke: #111110; }\n`;
|
|
432
|
+
css += `.stroke-transparent { stroke: transparent; }\n`;
|
|
427
433
|
css += `.stroke-0 { stroke-width: 0; }\n`;
|
|
428
434
|
css += `.stroke-1 { stroke-width: 1; }\n`;
|
|
429
435
|
css += `.stroke-2 { stroke-width: 2; }\n`;
|
|
@@ -602,6 +608,10 @@ function accessibilityUtilities() {
|
|
|
602
608
|
return `/* Accessibility */
|
|
603
609
|
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border-width: 0; }
|
|
604
610
|
.not-sr-only { position: static; width: auto; height: auto; padding: 0; margin: 0; overflow: visible; clip: auto; white-space: normal; }
|
|
611
|
+
.sr-only-focusable:not(:focus):not(:focus-within) { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border-width: 0; }
|
|
612
|
+
.focus-ring:focus-visible { outline: 2px solid var(--color-brand-80); outline-offset: 2px; }
|
|
613
|
+
.focus-ring-inset:focus-visible { outline: 2px solid var(--color-brand-80); outline-offset: -2px; }
|
|
614
|
+
.focus-ring-none:focus-visible { outline: none; }
|
|
605
615
|
.focus-visible:focus { outline: 2px solid currentColor; outline-offset: 2px; }
|
|
606
616
|
.focus\\:outline-none:focus { outline: 2px solid transparent; outline-offset: 2px; }
|
|
607
617
|
|
|
@@ -756,8 +766,8 @@ function divideUtilities(spacing, colours) {
|
|
|
756
766
|
css += `.divide-${colourName}-${shade} > * + * { border-color: var(--color-${colourName}-${shade}); }\n`;
|
|
757
767
|
});
|
|
758
768
|
});
|
|
759
|
-
css += `.divide-white > * + * { border-color: #
|
|
760
|
-
css += `.divide-black > * + * { border-color: #
|
|
769
|
+
css += `.divide-white > * + * { border-color: #FAFAFA; }\n`;
|
|
770
|
+
css += `.divide-black > * + * { border-color: #111110; }\n`;
|
|
761
771
|
css += `.divide-transparent > * + * { border-color: transparent; }\n`;
|
|
762
772
|
css += `\n`;
|
|
763
773
|
return css;
|
package/src/index.js
CHANGED
|
@@ -693,8 +693,8 @@ function generateBorderUtilities(config) {
|
|
|
693
693
|
css += `.border-none { border-style: none; }\n`;
|
|
694
694
|
css += `.border-transparent { border-color: transparent; }\n`;
|
|
695
695
|
css += `.border-current { border-color: currentColor; }\n`;
|
|
696
|
-
css += `.border-black { border-color: #
|
|
697
|
-
css += `.border-white { border-color: #
|
|
696
|
+
css += `.border-black { border-color: #111110; }\n`;
|
|
697
|
+
css += `.border-white { border-color: #FAFAFA; }\n`;
|
|
698
698
|
|
|
699
699
|
const baseRadius = config.spacing.borderRadius['base'] || '8px';
|
|
700
700
|
css += `.rounded { border-radius: ${baseRadius}; }\n`;
|
|
@@ -791,9 +791,15 @@ function generateColourUtilities(colours) {
|
|
|
791
791
|
});
|
|
792
792
|
});
|
|
793
793
|
|
|
794
|
-
css += `.bg-white { background-color: #
|
|
794
|
+
css += `.bg-white { background-color: #FAFAFA; }\n`;
|
|
795
|
+
css += `.bg-black { background-color: #111110; }\n`;
|
|
795
796
|
css += `.bg-transparent { background-color: transparent; }\n`;
|
|
796
|
-
css += `.
|
|
797
|
+
css += `.bg-current { background-color: currentColor; }\n`;
|
|
798
|
+
|
|
799
|
+
css += `.text-white { color: #FAFAFA; }\n`;
|
|
800
|
+
css += `.text-black { color: #111110; }\n`;
|
|
801
|
+
css += `.text-transparent { color: transparent; }\n`;
|
|
802
|
+
css += `.text-current { color: currentColor; }\n`;
|
|
797
803
|
|
|
798
804
|
css += `\n`;
|
|
799
805
|
return css;
|
|
@@ -812,6 +818,63 @@ function generateSemanticColourUtilities(semanticColours) {
|
|
|
812
818
|
return css;
|
|
813
819
|
}
|
|
814
820
|
|
|
821
|
+
// ============================================================================
|
|
822
|
+
// ARIA & DATA-STATE VARIANTS
|
|
823
|
+
// ============================================================================
|
|
824
|
+
// Generates ARIA attribute and data-state variants for all utility classes.
|
|
825
|
+
// Selectors target the attribute value directly so they work without JS —
|
|
826
|
+
// just toggle the attribute and the utility activates.
|
|
827
|
+
//
|
|
828
|
+
// Usage in HTML:
|
|
829
|
+
// aria-expanded: class="aria-expanded:block" aria-expanded="true"
|
|
830
|
+
// data-open: class="data-open:flex" data-state="open"
|
|
831
|
+
//
|
|
832
|
+
// Output examples:
|
|
833
|
+
// .aria-expanded\:block[aria-expanded="true"] { display: block; }
|
|
834
|
+
// .data-open\:flex[data-state="open"] { display: flex; }
|
|
835
|
+
|
|
836
|
+
function addAriaDataVariants(css) {
|
|
837
|
+
const variants = [
|
|
838
|
+
{ name: 'aria-expanded', selector: '[aria-expanded="true"]' },
|
|
839
|
+
{ name: 'aria-selected', selector: '[aria-selected="true"]' },
|
|
840
|
+
{ name: 'aria-current', selector: '[aria-current="page"]' },
|
|
841
|
+
{ name: 'aria-disabled', selector: '[aria-disabled="true"]' },
|
|
842
|
+
{ name: 'data-open', selector: '[data-state="open"]' },
|
|
843
|
+
{ name: 'data-closed', selector: '[data-state="closed"]' },
|
|
844
|
+
];
|
|
845
|
+
|
|
846
|
+
let variantCss = css;
|
|
847
|
+
|
|
848
|
+
variants.forEach(variant => {
|
|
849
|
+
let variantRules = '';
|
|
850
|
+
const lines = css.split('\n');
|
|
851
|
+
|
|
852
|
+
lines.forEach(line => {
|
|
853
|
+
if (line.startsWith('.') && line.includes('{')) {
|
|
854
|
+
const className = line.split('{')[0].trim();
|
|
855
|
+
// Skip already-variant lines (contain ':' in class name) and special selectors
|
|
856
|
+
if (
|
|
857
|
+
!className.startsWith(':root') &&
|
|
858
|
+
!className.includes('@') &&
|
|
859
|
+
!className.includes('::') &&
|
|
860
|
+
!className.includes(':')
|
|
861
|
+
) {
|
|
862
|
+
const classWithoutDot = className.substring(1);
|
|
863
|
+
const ariaSelector = `.${variant.name}\\:${classWithoutDot}${variant.selector}`;
|
|
864
|
+
const ariaRule = line.replace(className, ariaSelector);
|
|
865
|
+
variantRules += ariaRule + '\n';
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
});
|
|
869
|
+
|
|
870
|
+
if (variantRules) {
|
|
871
|
+
variantCss += `\n/* ARIA/data-state variant: ${variant.name} */\n` + variantRules;
|
|
872
|
+
}
|
|
873
|
+
});
|
|
874
|
+
|
|
875
|
+
return variantCss;
|
|
876
|
+
}
|
|
877
|
+
|
|
815
878
|
// ============================================================================
|
|
816
879
|
// DARK MODE VARIANTS
|
|
817
880
|
// ============================================================================
|
|
@@ -983,6 +1046,65 @@ function generatePatternComponents() {
|
|
|
983
1046
|
margin-inline: auto;
|
|
984
1047
|
}
|
|
985
1048
|
|
|
1049
|
+
.prose-emily {
|
|
1050
|
+
max-width: 65ch;
|
|
1051
|
+
margin-inline: auto;
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
.prose-emily > * + * {
|
|
1055
|
+
margin-top: var(--space-4, 1rem);
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
.prose-emily h2,
|
|
1059
|
+
.prose-emily h3 {
|
|
1060
|
+
font-family: inherit;
|
|
1061
|
+
color: var(--color-neutral-90);
|
|
1062
|
+
line-height: 1.25;
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
.prose-emily h2 {
|
|
1066
|
+
font-size: var(--text-2xl, 24px);
|
|
1067
|
+
margin-top: var(--space-10, 2.5rem);
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
.prose-emily h3 {
|
|
1071
|
+
font-size: var(--text-xl, 20px);
|
|
1072
|
+
margin-top: var(--space-8, 2rem);
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
.prose-emily p,
|
|
1076
|
+
.prose-emily li {
|
|
1077
|
+
color: var(--color-neutral-70);
|
|
1078
|
+
line-height: 1.75;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
.prose-emily ul,
|
|
1082
|
+
.prose-emily ol {
|
|
1083
|
+
padding-left: var(--space-6, 1.5rem);
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
.prose-emily ul {
|
|
1087
|
+
list-style-type: disc;
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
.prose-emily ol {
|
|
1091
|
+
list-style-type: decimal;
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
.prose-emily a {
|
|
1095
|
+
color: var(--color-brand-80);
|
|
1096
|
+
text-decoration: underline;
|
|
1097
|
+
text-underline-offset: 2px;
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
.prose-emily code {
|
|
1101
|
+
font-size: var(--text-sm, 14px);
|
|
1102
|
+
background-color: var(--color-neutral-10);
|
|
1103
|
+
border: 1px solid var(--color-neutral-20);
|
|
1104
|
+
border-radius: var(--space-1, 0.25rem);
|
|
1105
|
+
padding: 0.125rem 0.375rem;
|
|
1106
|
+
}
|
|
1107
|
+
|
|
986
1108
|
/* ---- Composition ---- */
|
|
987
1109
|
|
|
988
1110
|
/* Vertical stack with consistent gap — replaces manual margin chains */
|
|
@@ -1421,6 +1543,7 @@ function buildFullFramework() {
|
|
|
1421
1543
|
utilityCss += filterUtilities();
|
|
1422
1544
|
|
|
1423
1545
|
utilityCss = addStateVariants(utilityCss);
|
|
1546
|
+
utilityCss = addAriaDataVariants(utilityCss);
|
|
1424
1547
|
utilityCss = addDarkModeVariants(utilityCss);
|
|
1425
1548
|
utilityCss = addResponsiveVariants(utilityCss, config);
|
|
1426
1549
|
|
|
@@ -1645,8 +1768,8 @@ function build(options = {}) {
|
|
|
1645
1768
|
const fullCssPath = getFullCssPath(config);
|
|
1646
1769
|
const result = buildProductionCss();
|
|
1647
1770
|
|
|
1648
|
-
console.log('
|
|
1649
|
-
console.log('
|
|
1771
|
+
console.log('\u2713 Generated production CSS: ' + path.relative(process.cwd(), result.outputPath));
|
|
1772
|
+
console.log('\u2713 File size: ' + (result.outputSize / 1024).toFixed(2) + ' KB');
|
|
1650
1773
|
|
|
1651
1774
|
if (!options.keepFull && fs.existsSync(fullCssPath)) {
|
|
1652
1775
|
try {
|
|
@@ -1683,6 +1806,7 @@ module.exports = {
|
|
|
1683
1806
|
generateFlexboxUtilities,
|
|
1684
1807
|
generateGridUtilities,
|
|
1685
1808
|
addStateVariants,
|
|
1809
|
+
addAriaDataVariants,
|
|
1686
1810
|
addResponsiveVariants,
|
|
1687
1811
|
generateFontCSS,
|
|
1688
1812
|
codeUtilities,
|
package/src/purge.js
CHANGED
|
@@ -173,7 +173,7 @@ function purgeBlock(block, usedClasses) {
|
|
|
173
173
|
.replace(/:/g, "\\\\:");
|
|
174
174
|
|
|
175
175
|
const boundaryRegex = new RegExp(
|
|
176
|
-
`\\.${escapedUsed}(?::[\\w\\-]
|
|
176
|
+
`\\.${escapedUsed}(?::[\\w\\-]+|\\[|[\\s,>+~]|$)`,
|
|
177
177
|
);
|
|
178
178
|
|
|
179
179
|
if (boundaryRegex.test(selector)) return true;
|
|
@@ -275,5 +275,5 @@ function purgeCSS(css, scanDir, config) {
|
|
|
275
275
|
module.exports = {
|
|
276
276
|
purgeCSS,
|
|
277
277
|
getAllFiles,
|
|
278
|
-
extractClassNames
|
|
279
|
-
};
|
|
278
|
+
extractClassNames
|
|
279
|
+
};
|