@mastors/core 1.2.0 → 1.2.2

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.
Files changed (2) hide show
  1. package/README.md +141 -810
  2. package/package.json +3 -3
package/README.md CHANGED
@@ -1,940 +1,271 @@
1
1
  # @mastors/core
2
2
 
3
- > The foundational layer of the Mastors ecosystem — design tokens, SCSS functions, mixins, generators, reset, responsive engine, and theme system.
3
+ > Foundational tokens, mixins, functions, reset, and responsive engine for the Mastors ecosystem.
4
4
 
5
- [![npm](https://img.shields.io/npm/v/@mastors/core.svg)](https://www.npmjs.com/package/@mastors/core)
5
+ [![npm version](https://img.shields.io/npm/v/@mastors/core.svg)](https://www.npmjs.com/package/@mastors/core)
6
6
  [![license](https://img.shields.io/badge/license-MIT-blue.svg)](../../LICENSE)
7
- [![sass](https://img.shields.io/badge/requires-sass%20%3E%3D1.80-CC6699.svg)](https://sass-lang.com)
8
-
9
- ---
10
-
11
- ## Table of Contents
12
-
13
- - [Overview](#overview)
14
- - [Installation](#installation)
15
- - [Usage](#usage)
16
- - [Full stylesheet import](#full-stylesheet-import)
17
- - [Public API (zero output)](#public-api-zero-output)
18
- - [TypeScript / JavaScript](#typescript--javascript)
19
- - [Configuration](#configuration)
20
- - [Feature flags](#feature-flags)
21
- - [Dark mode strategy](#dark-mode-strategy)
22
- - [Class prefix](#class-prefix)
23
- - [Config via public API](#config-via-public-api)
24
- - [Design Tokens](#design-tokens)
25
- - [Color](#color)
26
- - [Spacing](#spacing)
27
- - [Typography](#typography)
28
- - [Border Radius](#border-radius)
29
- - [Shadows](#shadows)
30
- - [Z-Index](#z-index)
31
- - [Opacity](#opacity)
32
- - [Transitions](#transitions)
33
- - [Functions](#functions)
34
- - [vars()](#vars)
35
- - [Mixins](#mixins)
36
- - [Breakpoints](#breakpoints)
37
- - [Theme](#theme)
38
- - [Elevation](#elevation)
39
- - [Transition](#transition)
40
- - [Container](#container)
41
- - [Pseudo](#pseudo)
42
- - [Responsive Engine](#responsive-engine)
43
- - [Container Queries](#container-queries)
44
- - [Fluid Typography](#fluid-typography)
45
- - [Theme System](#theme-system)
46
- - [Base Layer](#base-layer)
47
- - [Utility Classes](#utility-classes)
48
- - [Helpers](#helpers)
49
- - [Accessibility](#accessibility)
50
- - [Generator Engine](#generator-engine)
51
- - [Semantic Layer](#semantic-layer)
52
- - [Known Stubs](#known-stubs)
53
- - [Package Exports](#package-exports)
54
- - [Peer Dependencies](#peer-dependencies)
55
- - [Changelog](#changelog)
56
7
 
57
8
  ---
58
9
 
59
10
  ## Overview
60
11
 
61
- `@mastors/core` is the only required package in the Mastors ecosystem. It provides:
12
+ `@mastors/core` is the foundation of the Mastors SCSS ecosystem. It provides:
62
13
 
63
- - **Design tokens** — color, spacing, typography, radius, shadows, z-index, opacity, and transitions as SCSS maps
64
- - **Functions** — `rem()`, `em()`, `color()`, `spacing()`, `tint()`, `shade()`, `alpha()`, `contrast()`, `fluid()`, `map-deep-get()`, `map-collect()`, `str-replace()`, `vars()`
65
- - **Mixins** — `bp()`, `dark-mode()`, `light-mode()`, `theme()`, `elevation()`, `transition()`, `container()`, `pseudo()`
66
- - **Generator engine** — `generate-utilities()`, `emit-custom-properties()`, and responsive-generator mixins used by all utility packages
67
- - **Reset** — modern CSS reset and document defaults
68
- - **Theme system** — CSS custom property-based light/dark theming with a full semantic contract
69
- - **Responsive engine** — breakpoint-aware utility variant generation (`sm:`, `md:`, `lg:`, `xl:`, `2xl:`)
70
- - **Container queries** — `.cq-inline`, `.cq-size`, `cq()` mixin for `@container` rules
71
- - **Fluid typography** — `fluid-type()` mixin and function using `clamp()`
72
- - **Utility classes** — display, position, overflow, spacing, sizing, colors, borders (full directional radius scale), shadows, opacity, cursor, z-index, transforms, typography, animation, interaction, layout (aspect-ratio, object-fit/position, blend modes)
73
- - **Accessibility** — focus ring, reduced-motion, screen-reader utilities, print layer
74
- - **TypeScript types and runtime token mirror**
14
+ - **Token system** — color, spacing, typography, radii, shadows, z-index, opacity, transitions, sizing
15
+ - **Functions** — `rem()`, `em()`, `color()`, `spacing()`, `vars()`, `tint()`, `shade()`, `fluid()`, and more
16
+ - **Mixins** — `bp()`, `dark-mode()`, `theme()`, `elevation()`, `transition()`, `container()`, `pseudo()`
17
+ - **Generator engine** — `generate-utilities()`, `emit-custom-properties()`, `generate-responsive()`
18
+ - **Utility classes** — display, spacing, sizing, colors, borders, shadows, typography, animation, interaction, layout, accessibility
19
+ - **Theme system** — CSS custom property contract, light/dark themes, `data-theme` support
20
+ - **Responsive engine** — breakpoint-prefixed variant generation, container queries, fluid typography
21
+ - **TypeScript mirror** — runtime token access and full type definitions
75
22
 
76
- All other `@mastors/*` packages consume `@mastors/core/api` for shared tokens, functions, and mixins.
23
+ All other `@mastors/*` packages consume `@mastors/core/api` as a peer dependency.
77
24
 
78
25
  ---
79
26
 
80
27
  ## Installation
81
28
 
82
29
  ```bash
83
- npm install @mastors/core sass
30
+ npm install @mastors/core
84
31
  # or
85
- pnpm add @mastors/core sass
32
+ pnpm add @mastors/core
33
+ # or
34
+ yarn add @mastors/core
86
35
  ```
87
36
 
88
- `sass >= 1.80.0` is required as a peer dependency.
37
+ Requires `sass >= 1.80.0` as a peer dependency:
38
+
39
+ ```bash
40
+ npm install --save-dev sass
41
+ ```
89
42
 
90
43
  ---
91
44
 
92
45
  ## Usage
93
46
 
94
- ### Full stylesheet import
95
-
96
- Import the complete compiled stylesheet — reset, tokens, themes, utilities, helpers, and accessibility:
47
+ ### Import the full stylesheet
97
48
 
98
49
  ```scss
99
50
  @use "@mastors/core/scss";
100
51
  ```
101
52
 
102
- ### Public API (zero output)
53
+ This imports the complete output: reset, custom properties, themes, utilities, helpers, and accessibility classes.
103
54
 
104
- Import only the public API surface. No CSS is emitted — you get access to all tokens, functions, mixins, and config:
55
+ ### Use the public API (zero CSS output)
105
56
 
106
57
  ```scss
107
58
  @use "@mastors/core/api" as m;
108
59
 
109
60
  .card {
110
- padding: m.spacing(6);
111
- background-color: m.color("neutral", 50);
112
- border-radius: m.radius("xl");
113
- box-shadow: m.vars(shadow-md);
114
- transition: box-shadow m.vars(duration-200) m.vars(ease-out);
61
+ padding: m.spacing(6);
62
+ color: m.color("primary", 700);
63
+ border-radius: m.radius("lg");
64
+ box-shadow: m.vars(shadow-md);
65
+ transition: transform m.vars(duration-200) m.vars(ease-out);
115
66
 
116
- @include m.bp("lg") {
67
+ @include m.bp("md") {
117
68
  padding: m.spacing(10);
118
69
  }
119
70
 
120
71
  @include m.dark-mode {
121
- background-color: m.color("neutral", 800);
122
- color: m.color("neutral", 100);
72
+ color: m.color("primary", 300);
123
73
  }
124
74
  }
125
75
  ```
126
76
 
127
- ### TypeScript / JavaScript
128
-
129
- Access design token values at runtime for CSS-in-JS, design tools, or testing:
130
-
131
- ```ts
132
- import { tokens } from '@mastors/core'
133
-
134
- const primary600 = tokens.color.primary['600'] // '#2563eb'
135
- const spacing4 = tokens.spacing['4'] // '1rem'
136
- const shadowMd = tokens.shadow.md // '0 4px 6px ...'
137
- const radiusXl = tokens.radius.xl // '0.75rem'
138
- const duration200 = tokens.duration['200'] // '200ms'
139
- ```
140
-
141
- Import TypeScript types:
142
-
143
- ```ts
144
- import type {
145
- MastorsConfig,
146
- Breakpoint,
147
- ThemeMode,
148
- Tokens,
149
- ColorPalette,
150
- SpacingKey,
151
- RadiusKey,
152
- } from '@mastors/core'
153
- ```
154
-
155
- ---
156
-
157
- ## Configuration
158
-
159
- Override the global config map before importing core to customise behaviour. The config must be set before any `@use "@mastors/core"` statement in your project.
77
+ ### Import a single partial
160
78
 
161
79
  ```scss
162
- // styles/_config.scss — set BEFORE @use "@mastors/core"
163
- @use "@mastors/core/scss/config/settings" with (
164
- $mastors-config: (
165
- "prefix": "", // optional class prefix, e.g. "m-" -> .m-flex
166
- "important": false, // append !important to all utility declarations
167
- "dark-mode": "class", // "class" | "media"
168
- "rtl": false, // enable RTL logical property variants
169
- )
170
- );
80
+ @use "@mastors/core/scss/tokens/color" as colors;
81
+ @use "@mastors/core/scss/mixins/breakpoint" as bp;
171
82
  ```
172
83
 
173
- ### Feature flags
84
+ ### JavaScript / TypeScript
174
85
 
175
- Disable any layer you don't need to reduce output size:
86
+ ```ts
87
+ import { tokens } from '@mastors/core'
88
+ import type { Breakpoint, SpacingKey, ColorPalette } from '@mastors/core'
176
89
 
177
- ```scss
178
- @use "@mastors/core/scss/config/flags" with (
179
- $enable-utilities: true,
180
- $enable-responsive: true,
181
- $enable-helpers: true,
182
- $enable-a11y: true,
183
- $enable-themes: true,
184
- );
90
+ const primary = tokens.color.primary['600'] // '#2563eb'
91
+ const space4 = tokens.spacing['4'] // '1rem'
185
92
  ```
186
93
 
187
- ### Dark mode strategy
94
+ ---
188
95
 
189
- **Class-based** (default) — add `.dark` or `data-theme="dark"` to `<html>`:
96
+ ## Package Exports
190
97
 
191
- ```html
192
- <html class="dark">...</html>
98
+ ```json
99
+ {
100
+ ".": { "import": "./dist/index.mjs", "require": "./dist/index.js", "types": "./dist/index.d.ts" },
101
+ "./scss": "./scss/index.scss",
102
+ "./scss/*": "./scss/*",
103
+ "./api": "./scss/api/_index.scss",
104
+ "./dist/mastors-core.css": "./dist/mastors-core.css"
105
+ }
193
106
  ```
194
107
 
195
- **Media-query** — responds automatically to the OS preference:
108
+ ---
196
109
 
197
- ```scss
198
- @use "@mastors/core/scss/config/settings" with (
199
- $mastors-config: ("dark-mode": "media")
200
- );
201
- ```
110
+ ## Public API (`@mastors/core/api`)
202
111
 
203
- ### Class prefix
112
+ Importing `@mastors/core/api` gives access to:
204
113
 
205
- Add a prefix to every generated utility class to prevent collisions:
114
+ ### Functions
206
115
 
207
- ```scss
208
- $mastors-config: ("prefix": "m-") !default;
209
- // .m-flex, .m-block, .m-grid-cols-3, ...
210
- ```
211
-
212
- ### Config via public API
213
-
214
- As of v1.2, both the `$mastors-config` map / `config()` accessor and all `$enable-*` flags are forwarded through the public API surface. Downstream consumers no longer need a direct partial import to read them:
116
+ | Function | Description |
117
+ |---|---|
118
+ | `color($name, $shade)` | Look up a palette color by name and shade |
119
+ | `spacing($key)` | Look up a spacing token |
120
+ | `radius($key)` | Look up a border-radius token |
121
+ | `shadow($key)` | Look up a box-shadow token |
122
+ | `z($key)` | Look up a z-index token |
123
+ | `opacity($key)` | Look up an opacity token |
124
+ | `duration($key)` | Look up a transition duration |
125
+ | `easing($key)` | Look up an easing curve |
126
+ | `vars($token, $fallback?)` | Emit `var(--mastors-{token})` with optional fallback |
127
+ | `rem($px)` | Convert px to rem |
128
+ | `em($px, $base?)` | Convert px to em |
129
+ | `tint($color, $amount)` | Mix color toward white |
130
+ | `shade($color, $amount)` | Mix color toward black |
131
+ | `alpha($color, $opacity)` | Set color opacity |
132
+ | `fluid($min, $max, $min-bp?, $max-bp?)` | Generate a fluid `clamp()` value |
133
+
134
+ ### Mixins
135
+
136
+ | Mixin | Description |
137
+ |---|---|
138
+ | `bp($key)` | Mobile-first breakpoint media query |
139
+ | `breakpoint-up($key)` | Alias for `bp()` |
140
+ | `breakpoint-down($key)` | Max-width media query |
141
+ | `respond-to($key)` | Alias for `bp()` |
142
+ | `dark-mode` | Dark mode block (class or media, per config) |
143
+ | `light-mode` | Light mode block |
144
+ | `theme($name)` | `[data-theme="name"]` scoped block |
145
+ | `elevation($level)` | Token-driven box-shadow by level |
146
+ | `transition($props...)` | Token-driven transition shorthand |
147
+ | `container($size?)` | Responsive container width |
148
+ | `pseudo($display, $pos, $content)` | `::before` / `::after` boilerplate |
149
+ | `cq($size, $name?)` | Container query block |
150
+ | `fluid-type($min, $max, $min-bp?, $max-bp?)` | Fluid font-size via `clamp()` |
151
+
152
+ ### Config
215
153
 
216
154
  ```scss
217
155
  @use "@mastors/core/api" as m;
218
156
 
219
- // Read a config value
220
- $prefix: m.config("prefix");
157
+ // Read config values
158
+ $mode: m.config("dark-mode"); // "class" | "media"
221
159
 
222
- // Read feature flags
223
- @if m.$enable-responsive {
224
- // emit responsive variants
225
- }
160
+ // Check feature flags
161
+ $enabled: m.$enable-flexer;
226
162
  ```
227
163
 
228
164
  ---
229
165
 
230
- ## Design Tokens
231
-
232
- All tokens are available via the public API after `@use "@mastors/core/api" as m`.
166
+ ## Token Reference
233
167
 
234
168
  ### Color
235
169
 
236
- Six semantic palettes, each with 11 shades (50-950), plus `white`, `black`, and `transparent`.
170
+ Palette keys: `primary`, `secondary`, `neutral`, `success`, `warning`, `danger`, `info`
171
+ Shades: `50`, `100`, `200`, `300`, `400`, `500`, `600`, `700`, `800`, `900`, `950`
237
172
 
238
173
  ```scss
239
- m.color("primary", 600) // #2563eb
240
- m.color("neutral", 100) // #f3f4f6
241
- m.color("success", 500) // #22c55e
242
- m.color("warning", 400) // #fbbf24
243
- m.color("error", 600) // #dc2626
244
- m.color("info", 500) // #06b6d4
245
- m.color("white") // #ffffff
246
- m.color("black") // #000000
174
+ m.color("primary", 600) // #2563eb
175
+ m.color("neutral", 100) // #f5f5f5
247
176
  ```
248
177
 
249
- Palettes: `primary` - `neutral` - `success` - `warning` - `error` - `info`
250
-
251
178
  ### Spacing
252
179
 
253
- 35-step scale from `0` to `96` (matching Tailwind's spacing scale):
254
-
255
- ```scss
256
- m.spacing(0) // 0px
257
- m.spacing(1) // 0.25rem
258
- m.spacing(4) // 1rem
259
- m.spacing(8) // 2rem
260
- m.spacing(16) // 4rem
261
- m.spacing(96) // 24rem
262
- ```
263
-
264
- Half-step keys (`0.5`, `1.5`, `2.5`, `3.5`) are also available:
265
-
266
- ```scss
267
- m.spacing("0.5") // 0.125rem
268
- m.spacing("1.5") // 0.375rem
269
- ```
270
-
271
- ### Typography
272
-
273
- ```scss
274
- // Font sizes (xs -> 9xl)
275
- m.font-size("sm") // 0.875rem
276
- m.font-size("base") // 1rem
277
- m.font-size("2xl") // 1.5rem
278
- m.font-size("5xl") // 3rem
279
-
280
- // Font families
281
- m.font-family("sans") // system-ui, -apple-system, ...
282
- m.font-family("mono") // ui-monospace, SFMono-Regular, ...
283
-
284
- // Font weights
285
- m.font-weight("semibold") // 600
286
- m.font-weight("bold") // 700
287
-
288
- // Line heights
289
- m.line-height("tight") // 1.25
290
- m.line-height("normal") // 1.5
291
-
292
- // Letter spacing
293
- m.letter-spacing("wide") // 0.025em
294
- ```
295
-
296
- ### Border Radius
180
+ 35-step scale `0` through `96`:
297
181
 
298
182
  ```scss
299
- m.radius("none") // 0px
300
- m.radius("sm") // 0.125rem
301
- m.radius("md") // 0.375rem
302
- m.radius("lg") // 0.5rem
303
- m.radius("xl") // 0.75rem
304
- m.radius("2xl") // 1rem
305
- m.radius("3xl") // 1.5rem
306
- m.radius("full") // 9999px
183
+ m.spacing(0) // 0
184
+ m.spacing(1) // 0.25rem
185
+ m.spacing(4) // 1rem
186
+ m.spacing(16) // 4rem
307
187
  ```
308
188
 
309
- ### Shadows
310
-
311
- ```scss
312
- m.shadow("xs") // subtle shadow
313
- m.shadow("sm") // small shadow
314
- m.shadow("md") // medium shadow (default)
315
- m.shadow("lg") // large shadow
316
- m.shadow("xl") // extra large shadow
317
- m.shadow("2xl") // page-level shadow
318
- m.shadow("inner") // inset shadow
319
- m.shadow("none") // none
320
- ```
321
-
322
- ### Z-Index
323
-
324
- ```scss
325
- m.z("base") // 0
326
- m.z("raised") // 10
327
- m.z("dropdown") // 100
328
- m.z("sticky") // 200
329
- m.z("overlay") // 300
330
- m.z("modal") // 400
331
- m.z("toast") // 500
332
- m.z("tooltip") // 600
333
- m.z("max") // 9999
334
- ```
335
-
336
- ### Opacity
337
-
338
- ```scss
339
- m.opacity("0") // 0
340
- m.opacity("50") // 0.5
341
- m.opacity("75") // 0.75
342
- m.opacity("100") // 1
343
- ```
344
-
345
- ### Transitions
346
-
347
- ```scss
348
- m.duration("150") // 150ms
349
- m.duration("200") // 200ms
350
- m.duration("300") // 300ms
351
-
352
- m.easing("in-out") // cubic-bezier(0.4, 0, 0.2, 1)
353
- m.easing("out") // cubic-bezier(0, 0, 0.2, 1)
354
- m.easing("bounce") // cubic-bezier(0.34, 1.56, 0.64, 1)
355
- ```
356
-
357
- ---
358
-
359
- ## Functions
360
-
361
- | Function | Description | Example |
362
- |---|---|---|
363
- | `rem($px)` | Convert px to rem | `rem(16px)` -> `1rem` |
364
- | `em($px)` | Convert px to em | `em(16px)` -> `1em` |
365
- | `color($palette, $shade)` | Get a color token | `color("primary", 600)` |
366
- | `spacing($key)` | Get a spacing token | `spacing(4)` -> `1rem` |
367
- | `radius($key)` | Get a radius token | `radius("xl")` -> `0.75rem` |
368
- | `shadow($key)` | Get a shadow token | `shadow("md")` |
369
- | `z($key)` | Get a z-index token | `z("modal")` -> `400` |
370
- | `opacity($key)` | Get an opacity token | `opacity("50")` -> `0.5` |
371
- | `duration($key)` | Get a duration token | `duration("200")` -> `200ms` |
372
- | `easing($key)` | Get an easing token | `easing("in-out")` |
373
- | `tint($c, $pct)` | Mix color with white | `tint(blue, 20%)` |
374
- | `shade($c, $pct)` | Mix color with black | `shade(blue, 20%)` |
375
- | `alpha($c, $a)` | Adjust alpha channel | `alpha(blue, 0.5)` |
376
- | `contrast($bg)` | Black or white for contrast (1) | `contrast(#1e40af)` -> white |
377
- | `fluid($min, $max)` | Clamp-based fluid value | `fluid(1rem, 2rem)` |
378
- | `map-deep-get($map, $keys...)` | Deep nested map access | `map-deep-get($tokens, "primary", "600")` |
379
- | `map-collect($maps...)` | Shallow-merge multiple maps | `map-collect($a, $b)` |
380
- | `str-replace($str, $search)` | Replace substring | `str-replace("a-b", "-", "_")` |
381
- | `vars($token, $fallback?)` | CSS custom property reference | `vars(shadow-md)` -> `var(--mastors-shadow-md)` |
382
-
383
- (1) `contrast()` uses a simplified linear luminance approximation without sRGB gamma expansion. The threshold is set to `0.35` (not the WCAG `0.179`) to compensate for the missing gamma step — this gives correct results across the neutral scale. Suitable for UI decisions; implement full sRGB linearisation for strict WCAG 2.1 contrast-ratio auditing.
384
-
385
- ### vars()
386
-
387
- `vars()` lets you reference any emitted design token as a CSS custom property by name, without hard-coding the `--mastors-` prefix. If the token name ever changes or the prefix is reconfigured, only the function implementation needs to update — all call sites stay the same.
388
-
389
- ```scss
390
- @use "@mastors/core/api" as m;
391
-
392
- .button {
393
- // Basic token reference
394
- color: m.vars(accent);
395
- box-shadow: m.vars(shadow-sm);
396
-
397
- // With CSS fallback (passed through verbatim)
398
- background: m.vars(surface-raised, #f9fafb);
399
- transition: opacity m.vars(duration-150) m.vars(ease-out);
400
-
401
- &:hover {
402
- box-shadow: m.vars(shadow-md);
403
- transform: translateY(-1px);
404
- }
405
- }
406
-
407
- // Composes cleanly with other values in shorthand properties
408
- .chip {
409
- border: 1px solid m.vars(border);
410
- padding: m.rem(4px) m.rem(10px);
411
- }
412
- ```
413
-
414
- Token names follow the same `--mastors-{name}` convention used in `:root`. Common examples:
415
-
416
- | Call | Emits |
417
- |---|---|
418
- | `m.vars(accent)` | `var(--mastors-accent)` |
419
- | `m.vars(surface)` | `var(--mastors-surface)` |
420
- | `m.vars(shadow-lg)` | `var(--mastors-shadow-lg)` |
421
- | `m.vars(duration-200)` | `var(--mastors-duration-200)` |
422
- | `m.vars(ease-in-out)` | `var(--mastors-ease-in-out)` |
423
- | `m.vars(border, #e5e7eb)` | `var(--mastors-border, #e5e7eb)` |
424
-
425
- ---
426
-
427
- ## Mixins
428
-
429
189
  ### Breakpoints
430
190
 
431
- Mobile-first, min-width media queries using the named breakpoint map.
432
-
433
- ```scss
434
- // Breakpoints: xs (0px) - sm (640px) - md (768px) - lg (1024px) - xl (1280px) - 2xl (1536px)
435
-
436
- @include m.bp("md") {
437
- // Applies at 768px and above
438
- }
439
-
440
- @include m.breakpoint-down("lg") {
441
- // Applies below 1024px
442
- }
443
-
444
- // Aliases
445
- @include m.respond-to("xl") { ... }
446
- @include m.breakpoint-up("sm") { ... }
447
- ```
448
-
449
- ### Theme
450
-
451
- ```scss
452
- @include m.dark-mode {
453
- // Activates when .dark is on <html> (class mode)
454
- // or prefers-color-scheme: dark (media mode)
455
- background-color: m.color("neutral", 900);
456
- }
457
-
458
- @include m.light-mode {
459
- background-color: m.color("white");
460
- }
461
-
462
- @include m.theme("ocean") {
463
- // Activates under [data-theme="ocean"]
464
- --accent: #0891b2;
465
- }
466
- ```
467
-
468
- ### Elevation
469
-
470
- ```scss
471
- @include m.elevation("sm"); // box-shadow: 0 1px 3px ...
472
- @include m.elevation("lg"); // box-shadow: 0 10px 15px ...
473
- @include m.elevation("none"); // box-shadow: none
474
- ```
475
-
476
- ### Transition
477
-
478
- ```scss
479
- // All properties, 200ms, in-out easing (defaults)
480
- @include m.transition();
481
-
482
- // Specific properties
483
- @include m.transition((color, background-color), "150", "out");
484
-
485
- // Custom combination
486
- @include m.transition((transform, opacity), "300", "bounce");
487
- ```
488
-
489
- ### Container
490
-
491
- ```scss
492
- .page-section {
493
- @include m.container();
494
- // max-width per breakpoint, auto horizontal margins, configurable padding
495
- }
496
- ```
497
-
498
- ### Pseudo
499
-
500
- ```scss
501
- .icon::before {
502
- @include m.pseudo();
503
- // Sets display: block, position: absolute, content: ""
504
- }
505
- ```
506
-
507
- ---
508
-
509
- ## Responsive Engine
510
-
511
- The engine in `responsive/_engine.scss` wraps utility maps in breakpoint media queries. Sub-packages can call `@include engine.run($utilities)` directly for standalone use.
512
-
513
- For the standard workflow, responsive variant generation is built into `generate-utilities()` — any utility entry that declares `responsive: true` automatically emits both base classes and breakpoint-prefixed variants in a single call. No separate invocation is required.
514
-
515
- Generated class pattern: `.{breakpoint}\:{class}`
516
-
517
- ```html
518
- <!-- Responsive display -->
519
- <div class="hidden md:block lg:flex">...</div>
520
-
521
- <!-- Responsive position -->
522
- <div class="relative md:absolute lg:sticky">...</div>
523
-
524
- <!-- Responsive layout (from @mastors/flexer or @mastors/gridder) -->
525
- <div class="flex flex-col md:flex-row lg:gap-8">...</div>
526
- ```
527
-
528
- Utilities with responsive support at v1.0: `display`, `position`.
529
- Additional responsive utilities added in v1.2: `text-align`, `float`, `flex-direction` (via flexer), `grid-template-columns` (via gridder).
530
-
531
- ---
532
-
533
- ## Container Queries
534
-
535
- Container queries are supported via `responsive/_container-queries.scss`.
536
-
537
- **Setup classes:**
538
-
539
- | Class | Effect |
191
+ | Key | Min-width |
540
192
  |---|---|
541
- | `.cq-inline` | `container-type: inline-size` |
542
- | `.cq-size` | `container-type: size` |
543
- | `.cq-normal` | `container-type: normal` |
544
- | `[data-container]` | `container-type: inline-size` (attribute-based) |
193
+ | `xs` | 0px (base) |
194
+ | `sm` | 640px |
195
+ | `md` | 768px |
196
+ | `lg` | 1024px |
197
+ | `xl` | 1280px |
198
+ | `2xl` | 1536px |
545
199
 
546
- **Usage:**
200
+ ### Radii
547
201
 
548
- ```html
549
- <div class="cq-inline">
550
- <div class="child">Responds to container width, not viewport</div>
551
- </div>
552
- ```
202
+ `none`, `sm`, `md`, `lg`, `xl`, `2xl`, `3xl`, `full`
553
203
 
554
- ```scss
555
- @use "@mastors/core/api" as m;
556
-
557
- .child {
558
- font-size: 1rem;
559
-
560
- @include m.cq(40rem) {
561
- font-size: 1.25rem;
562
- }
563
-
564
- // Named container query
565
- @include m.cq(30rem, "card") {
566
- padding: m.spacing(6);
567
- }
568
- }
569
- ```
570
-
571
- ---
572
-
573
- ## Fluid Typography
574
-
575
- `responsive/_fluid-type.scss` provides clamp()-based fluid font sizes that scale between two viewport widths without media queries.
576
-
577
- ```scss
578
- @use "@mastors/core/api" as m;
204
+ ### Shadows
579
205
 
580
- // As a mixin (applies font-size property)
581
- h1 { @include m.fluid-type(2rem, 3.75rem); }
206
+ `xs`, `sm`, `md`, `lg`, `xl`, `2xl`, `inner`, `none`
582
207
 
583
- // As a function (use in any property value)
584
- h1 { font-size: m.fluid-type(2rem, 3.75rem); }
208
+ ### Durations
585
209
 
586
- // Custom viewport range
587
- h2 { @include m.fluid-type(1.5rem, 3rem, 480px, 1440px); }
588
- ```
210
+ `75`, `100`, `150`, `200`, `300`, `500`, `700`, `1000` (ms)
589
211
 
590
- Opt-in preset scale for all heading levels:
212
+ ### Easings
591
213
 
592
- ```scss
593
- @use "@mastors/core/scss/responsive/fluid-type" as ft;
594
- @include ft.fluid-scale();
595
- // Applies fluid-type() to h1-h6 and p
596
- ```
214
+ `linear`, `in`, `out`, `in-out`
597
215
 
598
216
  ---
599
217
 
600
218
  ## Theme System
601
219
 
602
- Core emits all design tokens as `--mastors-*` CSS custom properties on `:root`. Theme layers override a semantic subset.
603
-
604
- **Default (light) theme properties:**
605
-
606
- ```css
607
- :root {
608
- --mastors-bg: #ffffff;
609
- --mastors-bg-subtle: #f9fafb;
610
- --mastors-surface: #ffffff;
611
- --mastors-surface-raised: #f9fafb;
612
- --mastors-surface-overlay: #f3f4f6;
613
- --mastors-text: #111827;
614
- --mastors-text-muted: #6b7280;
615
- --mastors-text-subtle: #9ca3af;
616
- --mastors-text-inverse: #ffffff;
617
- --mastors-border: #e5e7eb;
618
- --mastors-border-strong: #9ca3af;
619
- --mastors-accent: #2563eb;
620
- --mastors-accent-hover: #1d4ed8;
621
- --mastors-accent-subtle: #eff6ff;
622
- --mastors-accent-text: #ffffff;
623
- }
624
- ```
625
-
626
- **Dark theme** activates via `.dark` on `<html>` (or `prefers-color-scheme` in media mode):
627
-
628
- ```html
629
- <html class="dark">...</html>
630
- ```
631
-
632
- Use semantic custom properties directly in your CSS for automatic theme switching:
633
-
634
- ```css
635
- .card {
636
- background-color: var(--mastors-surface);
637
- color: var(--mastors-text);
638
- border-color: var(--mastors-border);
639
- }
640
- ```
641
-
642
- Or use `vars()` in SCSS for the same result without the prefix noise:
643
-
644
220
  ```scss
645
- .card {
646
- background-color: m.vars(surface);
647
- color: m.vars(text);
648
- border-color: m.vars(border);
649
- }
221
+ // Class-based dark mode (default)
222
+ // Activate with: <html class="dark">
223
+ $mastors-config: ("dark-mode": "class") !default;
224
+
225
+ // Media-query dark mode
226
+ $mastors-config: ("dark-mode": "media") !default;
650
227
  ```
651
228
 
652
- Custom themes can be applied with any `data-theme` attribute:
229
+ Custom theme:
653
230
 
654
231
  ```scss
655
- @use "@mastors/core/api" as m;
656
-
657
232
  @include m.theme("ocean") {
658
233
  --mastors-accent: #0891b2;
659
- --mastors-accent-hover: #0e7490;
660
234
  }
661
235
  ```
662
236
 
663
237
  ```html
664
- <div data-theme="ocean">
665
- <!-- accent color is teal inside here -->
666
- </div>
238
+ <div data-theme="ocean">...</div>
667
239
  ```
668
240
 
669
241
  ---
670
242
 
671
- ## Base Layer
672
-
673
- The base layer emits a modern CSS reset and document defaults when you import the full stylesheet:
674
-
675
- - `box-sizing: border-box` on all elements (declared once in `_reset.scss`)
676
- - Zero margin and padding on all elements
677
- - `img`, `video`, `canvas`, `svg` set to `display: block; max-width: 100%`
678
- - `input`, `button`, `textarea`, `select` inherit font
679
- - Smooth scroll behaviour on `html`
680
- - `-webkit-font-smoothing: antialiased` on `body`
681
- - Base `color` and `background-color` on `html` driven by semantic custom properties
682
- - Heading sizes (h1-h6) driven by the typography token scale
683
- - Code/pre elements default to the mono font family
684
-
685
- ---
686
-
687
- ## Utility Classes
688
-
689
- When importing the full stylesheet, core emits these utility classes:
690
-
691
- | Group | Classes |
692
- |---|---|
693
- | Display | `.block` `.inline-block` `.inline` `.flex` `.inline-flex` `.grid` `.inline-grid` `.hidden` `.contents` `.table` `.table-cell` `.table-row` |
694
- | Position | `.static` `.relative` `.absolute` `.fixed` `.sticky` - `.inset-*` `.top-*` `.right-*` `.bottom-*` `.left-*` |
695
- | Overflow | `.overflow-auto/hidden/scroll/visible/clip` - `.overflow-x-*` `.overflow-y-*` |
696
- | Spacing | `.m-*` `.mx-*` `.my-*` `.mt/r/b/l/s/e-*` - `.p-*` `.px-*` `.py-*` `.pt/r/b/l/s/e-*` - `.gap-*` `.gap-x-*` `.gap-y-*` |
697
- | Sizing | `.w-*` `.h-*` - `.min-w-*` `.max-w-*` `.min-h-*` `.max-h-*` |
698
- | Colors | `.text-*` `.bg-*` (all palettes x all shades + semantic) |
699
- | Borders | `.border` `.border-*` `.rounded-*` `.rounded-{t\|b\|l\|r}-*` (full scale, all token steps) |
700
- | Shadows | `.shadow-*` |
701
- | Opacity | `.opacity-*` |
702
- | Cursor | `.cursor-pointer` `.cursor-not-allowed` `.cursor-grab` etc. |
703
- | Pointer events | `.pointer-events-none` `.pointer-events-auto` |
704
- | Z-index | `.z-base` `.z-dropdown` `.z-modal` `.z-tooltip` etc. |
705
- | Transforms | `.translate-x-*` `.translate-y-*` `.rotate-*` `.scale-*` `.origin-*` `.transform-gpu` `.transform-none` |
706
- | Typography | `.text-{left\|center\|right\|justify\|start\|end}` (responsive) · `.text-{xs…9xl}` · `.font-{thin…black}` · `.font-{sans\|mono\|display}` · `.italic` `.not-italic` · `.leading-*` · `.tracking-*` · `.underline` `.overline` `.line-through` `.no-underline` · `.decoration-{solid\|dashed\|dotted\|double\|wavy}` · `.decoration-{1\|2\|4\|8}` · `.uppercase` `.lowercase` `.capitalize` `.normal-case` · `.text-ellipsis` `.text-clip` · `.whitespace-*` · `.break-normal` `.break-words` `.break-all` `.break-keep` · `.align-{baseline\|top\|middle\|bottom}` · `.list-none` `.list-disc` `.list-decimal` · `.antialiased` `.subpixel-antialiased` |
707
- | Animation | `.transition` `.transition-{colors\|opacity\|shadow\|transform\|none\|all}` · `.duration-*` · `.ease-*` · `.delay-*` · `.animate-{spin\|ping\|pulse\|bounce\|fade-in\|fade-out\|slide-up\|slide-down\|scale-in\|none}` · `.fill-{none\|forwards\|backwards\|both}` · `.animation-{running\|paused}` · `.animate-repeat-{0\|1\|infinite}` |
708
- | Interaction | `.select-{none\|text\|all\|auto}` · `.resize-{none\|x\|y}` `.resize` · `.scroll-{auto\|smooth}` · `.snap-{none\|x\|y\|both\|mandatory\|proximity}` · `.snap-{start\|end\|center}` · `.snap-stop-{always\|normal}` · `.scroll-m-*` `.scroll-p-*` · `.touch-{auto\|none\|pan-x\|pan-y\|manipulation}` · `hover:opacity-*` `hover:bg-accent` `hover:underline` `hover:shadow-lg` `hover:scale-{105\|110}` `hover:-translate-y-1` · `focus:ring` `focus:ring-2` `focus:ring-offset-2` `focus:ring-none` · `disabled:opacity-50` `disabled:cursor-not-allowed` `disabled:pointer-events-none` |
709
- | Layout | `.aspect-{auto\|square\|video\|4-3\|3-2\|21-9\|9-16\|golden}` · `.object-{contain\|cover\|fill\|none\|scale-down}` · `.object-{center\|top\|bottom\|left\|right\|…}` · `.float-{left\|right\|none\|start\|end}` (responsive) · `.clear-*` · `.isolate` `.isolation-auto` · `.mix-blend-*` · `.bg-blend-*` · `.box-decoration-{clone\|slice}` · `.appearance-{none\|auto}` · `.will-change-{auto\|scroll\|contents\|transform}` |
710
-
711
- Display and position utilities support responsive prefixes (`sm:`, `md:`, `lg:`, `xl:`, `2xl:`). Text-align and float also support responsive prefixes.
712
-
713
- ---
714
-
715
- ## Helpers
716
-
717
- | Class | Effect |
718
- |---|---|
719
- | `.visually-hidden`, `.vh` | Visually hidden, screen-reader accessible |
720
- | `.visually-hidden-focusable` | Hidden until focused (use for skip links) |
721
- | `.truncate` | Single-line text truncation with ellipsis |
722
- | `.line-clamp-{1-6}` | Multi-line text clamp |
723
- | `.break-words` | `overflow-wrap: break-word` |
724
- | `.break-all` | `word-break: break-all` |
725
- | `.break-keep` | `word-break: keep-all` |
726
- | `.ratio-auto` | `aspect-ratio: auto` |
727
- | `.ratio-square` | `aspect-ratio: 1 / 1` |
728
- | `.ratio-video` | `aspect-ratio: 16 / 9` |
729
- | `.ratio-portrait` | `aspect-ratio: 3 / 4` |
730
- | `.ratio-wide` | `aspect-ratio: 21 / 9` |
731
- | `.ratio-golden` | `aspect-ratio: 1.618 / 1` |
732
- | `.clearfix` | Float clearfix via `::after` |
733
-
734
- ---
735
-
736
- ## Accessibility
737
-
738
- | Class / Rule | Effect |
739
- |---|---|
740
- | `.sr-only` | Visually hidden, announced by screen readers |
741
- | `.not-sr-only` | Undoes `.sr-only` |
742
- | `.visually-hidden`, `.vh` | Equivalent to `.sr-only` with `!important` guards |
743
- | `.visually-hidden-focusable` | Hidden until focused (skip-link pattern) |
744
- | `:focus-visible` | 2px primary-500 ring, 2px offset — keyboard only |
745
- | `:focus:not(:focus-visible)` | Removes ring for mouse/pointer users |
746
- | `prefers-reduced-motion: reduce` | Collapses all animation/transition durations to 0.01ms |
747
- | `.print\:hidden` | `display: none` inside `@media print` |
748
- | `.screen\:hidden` | `display: none` outside `@media print` (print-only element) |
749
- | `.print\:break-inside-avoid` | Prevents page breaks inside the element when printing |
750
- | `.print\:break-before` | Forces a page break before the element |
751
- | `.print\:break-after` | Forces a page break after the element |
752
- | `.print\:text-black` | Forces `color: #000` for print output |
753
- | `.print\:bg-white` | Forces `background: #fff` for print output |
754
- | `.print\:border-none` | Removes borders for print output |
755
- | `.print\:shadow-none` | Removes box-shadow for print output |
756
- | `a[href]::after` *(print)* | Appends `(url)` after links so destinations are visible on paper |
243
+ ## Build
757
244
 
758
- ---
759
-
760
- ## Generator Engine
761
-
762
- The three generator mixins are the engine behind all utility class output in the Mastors ecosystem.
763
-
764
- ### `generate-utilities($utilities)`
765
-
766
- Generates utility classes from a configuration map. Used by `@mastors/flexer`, `@mastors/gridder`, and all core utility partials.
767
-
768
- The mixin runs in two passes:
769
- - **Pass 1** — emits base (unprefixed) classes for every entry.
770
- - **Pass 2** — for every entry with `responsive: true`, iterates all breakpoints (skipping `xs`/0px) and emits breakpoint-prefixed variants inside `@media` blocks. Respects the `$enable-responsive` flag and the global prefix/`!important` config.
771
-
772
- ```scss
773
- @use "@mastors/core/scss/generators/class-generator" as gen;
774
-
775
- @include gen.generate-utilities((
776
- "text-align": (
777
- property: text-align,
778
- prefix: "text",
779
- responsive: true,
780
- values: (
781
- "left": left,
782
- "center": center,
783
- "right": right,
784
- ),
785
- ),
786
- ));
787
- // Emits: .text-left, .text-center, .text-right
788
- // And: .sm\:text-left, .md\:text-left, … for all breakpoints
789
- ```
790
-
791
- ### `emit-custom-properties($map, $prefix)`
792
-
793
- Emits flat CSS custom properties from a token map onto the current selector.
794
-
795
- ```scss
796
- :root {
797
- @include gen.emit-custom-properties($spacing-tokens, "mastors-spacing");
798
- // -> --mastors-spacing-4: 1rem; etc.
799
- }
800
- ```
801
-
802
- ### `emit-nested-custom-properties($map, $prefix)`
803
-
804
- Recursively emits custom properties from a nested map (e.g. color palettes).
805
-
806
- ```scss
807
- :root {
808
- @include gen.emit-nested-custom-properties($color-tokens, "mastors-color");
809
- // -> --mastors-color-primary-500: #3b82f6; etc.
810
- }
811
- ```
812
-
813
- ---
814
-
815
- ## Semantic Layer
816
-
817
- The semantic layer in `semantic/` provides role-based SCSS variable aliases on top of the raw token maps. Use these in component SCSS instead of raw token references to get automatic theme compatibility.
818
-
819
- **Colors:**
820
-
821
- ```scss
822
- @use "@mastors/core/scss/semantic/colors" as sem;
823
-
824
- .my-card {
825
- background: sem.$color-surface; // var(--mastors-surface)
826
- color: sem.$color-text; // var(--mastors-text)
827
- border: 1px solid sem.$color-border; // var(--mastors-border)
828
- }
829
- ```
830
-
831
- **Spacing:**
832
-
833
- ```scss
834
- @use "@mastors/core/scss/semantic/spacing" as sem;
835
-
836
- .section {
837
- padding: sem.$space-section; // spacing(16) = 4rem
838
- gap: sem.$space-component; // spacing(4) = 1rem
839
- }
840
- ```
841
-
842
- **Typography:**
843
-
844
- ```scss
845
- @use "@mastors/core/scss/semantic/typography" as sem;
245
+ ```bash
246
+ # From the monorepo root
247
+ pnpm build:core
846
248
 
847
- body { font-family: sem.$font-body; } // system-ui stack
848
- code { font-family: sem.$font-mono; } // monospace stack
249
+ # Or from this package
250
+ node build.js
849
251
  ```
850
252
 
851
- ---
852
-
853
- ## Known Stubs
854
-
855
- Two files are intentionally empty at v1.0 and act as reserved extension points:
856
-
857
- | File | Purpose |
858
- |---|---|
859
- | `abstracts/_maps.scss` | Shared utility maps consumed by 3+ unrelated files. Empty until such maps exist. |
860
- | `vendors/_index.scss` | Third-party CSS overrides. Add a partial and `@forward` it here when needed. |
861
- | `base/_box-sizing.scss` | Retained as a named path slot; box-sizing is declared in `_reset.scss`. |
862
-
863
- These stubs are documented in each file's header comment.
864
-
865
- ---
866
-
867
- ## Package Exports
868
-
869
- ```scss
870
- /* Full stylesheet — reset + tokens + themes + utilities */
871
- @use "@mastors/core/scss";
253
+ Build steps: clean → compile SCSS → regenerate `src/tokens.ts` → compile TypeScript.
872
254
 
873
- /* Public API zero CSS output, all tokens/mixins/functions/config */
874
- @use "@mastors/core/api" as m;
255
+ To regenerate the TypeScript token mirror without a full build:
875
256
 
876
- /* Individual partials */
877
- @use "@mastors/core/scss/tokens/color" as ct;
878
- @use "@mastors/core/scss/mixins/breakpoint" as bp;
879
- @use "@mastors/core/scss/functions/rem" as r;
880
- @use "@mastors/core/scss/functions/vars"; /* vars() standalone */
881
- @use "@mastors/core/scss/responsive/fluid-type" as ft;
882
- @use "@mastors/core/scss/config/settings"; /* $mastors-config, config() */
883
- @use "@mastors/core/scss/config/flags"; /* $enable-* flags */
884
- ```
885
-
886
- ```ts
887
- // Runtime token access
888
- import { tokens } from '@mastors/core'
889
-
890
- // TypeScript types
891
- import type { MastorsConfig, Breakpoint, ThemeMode, Tokens } from '@mastors/core'
257
+ ```bash
258
+ node scripts/generate-tokens.js
892
259
  ```
893
260
 
894
- ---
895
-
896
- ## Peer Dependencies
897
-
898
- | Package | Version |
899
- |---|---|
900
- | `sass` | `>= 1.80.0` |
261
+ > `src/tokens.ts` is auto-generated — never edit it manually.
901
262
 
902
263
  ---
903
264
 
904
265
  ## Changelog
905
266
 
906
- ### v1.2.0
907
-
908
- - **Added:** `vars($token, $fallback?)` function in `functions/_vars.scss` — wraps the `--mastors-` namespace so downstream consumers reference tokens as `var(--mastors-{name})` without hard-coding the prefix. Namespace stored in `$-namespace: "mastors" !default`. Forwarded through `functions/_index.scss` and exposed via `@use "@mastors/core/api"`.
909
- - **Added:** `config/_index.scss` shim — `@forward`s both `_settings.scss` and `_flags.scss`. `api/_index.scss` now includes `@forward "../config/index"`, exposing `config()` accessor and all `$enable-*` flags through the public API surface without a direct partial import.
910
- - **Added:** `utilities/_typography.scss` — full typography utility surface covering text-align (responsive), font-size (token-driven `@each`), font-weight (token-driven), font-family (token-driven), font-style (`.italic` / `.not-italic`), line-height / leading (token-driven), letter-spacing / tracking (token-driven), text-decoration (line + style + thickness), text-transform, text-overflow, white-space, word-break, text-indent, vertical-align, list-style, font-smoothing.
911
- - **Added:** `utilities/_animation.scss` — transition-property presets (`.transition`, `.transition-colors`, `.transition-opacity`, `.transition-shadow`, `.transition-transform`, `.transition-none`, `.transition-all`), token-driven `.duration-*` and `.delay-*`, token-driven `.ease-*`, named animation presets (`.animate-spin/ping/pulse/bounce/fade-in/fade-out/slide-up/slide-down/scale-in/none`), full `@keyframes` definitions prefixed `mastors-*`, animation fill-mode / play-state / iteration utilities.
912
- - **Added:** `utilities/_interaction.scss` — user-select, resize, scroll-behavior (`.scroll-auto` / `.scroll-smooth`), scroll-snap (type + align + stop + scroll-margin/padding), touch-action, and state-variant pseudo-class utilities: `hover:opacity-*`, `hover:bg-accent`, `hover:text-accent`, `hover:underline`, `hover:no-underline`, `hover:shadow-lg`, `hover:scale-105`, `hover:scale-110`, `hover:-translate-y-1`, `focus:ring`, `focus:ring-2`, `focus:ring-offset-2`, `focus:ring-none`, `disabled:opacity-50`, `disabled:cursor-not-allowed`, `disabled:pointer-events-none`.
913
- - **Added:** `utilities/_layout.scss` — aspect-ratio block (`.aspect-auto`, `.aspect-square`, `.aspect-video`, `.aspect-4-3`, `.aspect-3-2`, `.aspect-21-9`, `.aspect-9-16`, `.aspect-golden`; the `$-aspect-ratios` map is `!default`-overridable). Documented alongside object-fit and object-position which were already present.
914
- - **Added:** `accessibility/_print.scss` — `print:hidden`, `screen:hidden`, `print:break-inside-avoid`, `print:break-before`, `print:break-after`, `print:text-black`, `print:bg-white`, `print:border-none`, `print:shadow-none`, automatic `a[href]::after` link expansion, suppression for `#` and `javascript:` links.
915
-
916
- ### v1.0.0
917
-
918
- - Initial public release
919
- - Full token system: color, spacing, typography, radii, shadows, z-index, opacity, transitions, sizing
920
- - Complete functions layer: `rem`, `em`, `color`, `spacing`, `radius`, `shadow`, `z`, `opacity`, `duration`, `easing`, `tint`, `shade`, `alpha`, `contrast`, `fluid`, `map-deep-get`, `map-collect`, `str-replace`
921
- - Complete mixins layer: `bp`, `respond-to`, `breakpoint-up`, `breakpoint-down`, `dark-mode`, `light-mode`, `theme`, `elevation`, `transition`, `container`, `pseudo`
922
- - **Fixed:** `generate-utilities()` now runs a two-pass emit — Pass 1 outputs base classes, Pass 2 automatically emits breakpoint-prefixed responsive variants for all entries with `responsive: true`. Previously responsive variants were silently not emitted.
923
- - **Fixed:** `generators/_responsive-generator.scss` replaced the `@content`-based no-op stub with a thin wrapper that correctly delegates to `engine.run()` for backward compatibility.
924
- - **Fixed:** `contrast()` luminance threshold corrected from `0.179` (WCAG linearised) to `0.35` (calibrated for the simplified non-gamma-expanded approximation in use). Prevents wrong light/dark decisions on mid-grey backgrounds.
925
- - **Added:** `stylelint` linting with `stylelint-config-standard-scss` — `pnpm lint` now runs real SCSS style checks. `postcss-scss`, `stylelint`, and `stylelint-config-standard-scss` added to `devDependencies`; `.stylelintrc.json` added to `packages/core`.
926
- - Generator engine: `generate-utilities` (with integrated responsive Pass 2), `emit-custom-properties`, `emit-nested-custom-properties`
927
- - Responsive engine with correct numeric breakpoint escaping (`2xl:` prefix)
928
- - Container queries: `.cq-inline`, `.cq-size`, `.cq-normal`, `[data-container]`, `cq()` mixin
929
- - Fluid typography: `fluid-type()` mixin + function + `fluid-scale()` preset
930
- - Full directional border-radius utility scale — all four sides x all token steps
931
- - Light and dark themes via CSS custom property semantic contract (15 semantic props)
932
- - Modern CSS reset — no duplicate `box-sizing` declarations
933
- - Accessibility layer: `:focus-visible` ring, `prefers-reduced-motion` override, `.sr-only`, `.visually-hidden`
934
- - Dual dark-mode strategy: class-based and media-query, configurable via `$mastors-config`
935
-
936
- ---
267
+ See the [root CHANGELOG](../../README.md#changelog).
937
268
 
938
269
  ## License
939
270
 
940
- MIT (c) Mastors Contributors
271
+ MIT © Mastors Contributors
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastors/core",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "Mastors Core — foundational tokens, mixins, functions, and SCSS architecture",
5
5
  "license": "MIT",
6
6
  "author": "Mastors Contributors",
@@ -51,8 +51,8 @@
51
51
  "stylelint-config-standard-scss": "^13.0.0",
52
52
  "typescript": "^5.3.0",
53
53
  "@mastors/build-utils": "2.0.0",
54
- "@mastors/sass-config": "1.0.1",
55
- "@mastors/tsconfig": "1.0.1"
54
+ "@mastors/tsconfig": "1.0.1",
55
+ "@mastors/sass-config": "1.0.1"
56
56
  },
57
57
  "peerDependencies": {
58
58
  "sass": ">=1.80.0"