@getvitops/generator 8.2.0 → 8.3.0-alpha.0

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.
@@ -68,6 +68,10 @@
68
68
  "type": "string"
69
69
  },
70
70
  "description": "Step → colour overrides (hex or oklch()) pinned VERBATIM at those steps. Every other step takes its lightness from the shared ladder, with chroma and hue interpolated between the anchors — so an anchor is reproduced exactly and is the only step allowed off the ladder. An explicit anchor overrides the seed at that step; two anchors that resolve to the same step are an error."
71
+ },
72
+ "acknowledgeOffLadder": {
73
+ "type": "boolean",
74
+ "description": "Acknowledge that this hue deliberately pins colours off the shared lightness ladder (typically to match an existing brand palette exactly). Silences the per-step \"off the ladder\" build warnings for THIS hue only; the monotonicity and contrast checks still run."
71
75
  }
72
76
  },
73
77
  "required": [
@@ -98,6 +102,10 @@
98
102
  }
99
103
  ],
100
104
  "description": "Fixed brand kit: authored tones placed verbatim at their nearest steps plus tinted off-white/off-black endpoints; no interpolation. Either an ordered light → dark array or a step → colour map."
105
+ },
106
+ "acknowledgeOffLadder": {
107
+ "type": "boolean",
108
+ "description": "Acknowledge that this hue deliberately pins colours off the shared lightness ladder (typically to match an existing brand palette exactly). Silences the per-step \"off the ladder\" build warnings for THIS hue only; the monotonicity and contrast checks still run."
101
109
  }
102
110
  },
103
111
  "required": [
@@ -135,6 +143,21 @@
135
143
  "chromatic"
136
144
  ],
137
145
  "description": "`surface` — a page/panel colour: gets a bare `bg-<role>` plus the full emphasis range and text scale. `chromatic` (default) — a signal colour: tints and solids only, no bare `bg-<role>`."
146
+ },
147
+ "solid": {
148
+ "description": "Ramp step (100…900) the role's solid family starts from; default 600. `bg-<role>-solid` is this step and `-solid-bold` / `-solid-x-bold` walk one and two rungs DARKER, so `solid: 400` gives 400 → 500 → 600. Use it when the brand colour is bright and lives lower on the ramp (a yellow at 400) instead of reaching for raw `bg-<hue>-<step>` classes. Like the default family it is the same in light and dark. The contrast check still runs on the pair this produces.",
149
+ "type": [
150
+ "number",
151
+ "string"
152
+ ]
153
+ },
154
+ "foreground": {
155
+ "type": "string",
156
+ "enum": [
157
+ "light",
158
+ "dark"
159
+ ],
160
+ "description": "Polarity of `text-on-<role>`, the foreground for a filled surface. Default is whichever of near-white / near-black has more contrast on the solid. Set `\"dark\"` so a bright fill carries dark text (or `\"light\"` for the reverse). The build still fails if the forced pair is below APCA Lc 60."
138
161
  }
139
162
  },
140
163
  "required": [
@@ -164,13 +187,31 @@
164
187
  "additionalProperties": false
165
188
  },
166
189
  "shadows": {
167
- "description": "Named shadows → `--shadow-<name>` tokens and `.drop-shadow-<name>` utilities. Values are shadow parameter lists (offset/blur/colour). Each token feeds two consumers with different grammars — `box-shadow` (pattern geometry, via the `--ds-*` group aliases) and `filter: drop-shadow(…)` (the utilities and the `shadow:` state shortcut) — so values must stay in the intersection: **one layer, no spread radius, no `inset`**. `drop-shadow()` rejects all three, and rejecting them invalidates the whole filter, so the shadow vanishes rather than degrading.",
190
+ "description": "Named shadows → `--shadow-<name>` tokens and `.drop-shadow-<name>` utilities. A value is either a string (below) or `{ \"box\"?: string, \"drop\"?: string }` for a shadow that needs the two grammars to differ: `box` is what `--shadow-<name>` holds and what `box-shadow` consumers (pattern geometry, `--ds-*`) read, so it MAY use spread, `inset` and several layers; `drop` is emitted as `--shadow-<name>-drop` and is what `.drop-shadow-<name>` and the `shadow:` state shortcut read, so it must obey the drop-shadow() limits. Omit `drop` and no drop-shadow utility is emitted for that name; omit `box` and `--shadow-<name>` takes the `drop` value. The plain string form keeps working and feeds both consumers from one value. For that string form: each token feeds two consumers with different grammars — `box-shadow` (pattern geometry, via the `--ds-*` group aliases) and `filter: drop-shadow(…)` (the utilities and the `shadow:` state shortcut) — so values must stay in the intersection: **one layer, no spread radius, no `inset`**. `drop-shadow()` rejects all three, and rejecting them invalidates the whole filter, so the shadow vanishes rather than degrading.",
168
191
  "type": "object",
169
192
  "propertyNames": {
170
193
  "type": "string"
171
194
  },
172
195
  "additionalProperties": {
173
- "type": "string"
196
+ "anyOf": [
197
+ {
198
+ "type": "string"
199
+ },
200
+ {
201
+ "type": "object",
202
+ "properties": {
203
+ "box": {
204
+ "type": "string",
205
+ "description": "`box-shadow` value: spread, `inset` and multiple layers allowed."
206
+ },
207
+ "drop": {
208
+ "type": "string",
209
+ "description": "`drop-shadow()` value: one layer, at most three lengths, no `inset`."
210
+ }
211
+ },
212
+ "additionalProperties": false
213
+ }
214
+ ]
174
215
  }
175
216
  },
176
217
  "fonts": {
@@ -184,7 +225,7 @@
184
225
  }
185
226
  },
186
227
  "typeScale": {
187
- "description": "Fluid modular TYPE scale → `--text-<name>` tokens, consumed by typography roles and text-size utilities.",
228
+ "description": "Fluid modular TYPE scale → `--text-<name>` tokens, consumed by typography roles and text-size utilities.\n\n**Recipe for marketing headings:** one ratio cannot serve both a ~16px body and a ~76px hero — a ratio big enough for the hero collapses the small end to unreadable. Extend `names` upward instead of raising the ratio: keep `base` ≈ \"1rem\" at the body step, `ratio` ≈ 1.2 at `maxVw` (≈ 1.125–1.15 `minRatio` at `minVw` so headings tame on phones), and add names (`4xl`, `5xl`) for the display sizes — the steps above `baseStep` are what headings read, the steps below it only need `xs`/`sm`. Aim the largest named step at your hero (≈ 4.5–5rem at `maxVw`), then point the `display`/`title` roles at those steps rather than hand-writing `clamp()` in a role. If a step still needs its own value, set that role's `size` literally — roles may bypass the scale.",
188
229
  "type": "object",
189
230
  "properties": {
190
231
  "base": {
@@ -245,6 +286,55 @@
245
286
  ],
246
287
  "additionalProperties": false
247
288
  },
289
+ "layout": {
290
+ "type": "object",
291
+ "properties": {
292
+ "widths": {
293
+ "type": "object",
294
+ "properties": {
295
+ "measure": {
296
+ "type": "string",
297
+ "description": "Reading column → `--width-measure` (framework default 65ch)."
298
+ },
299
+ "breakout": {
300
+ "type": "string",
301
+ "description": "`.breakout` track → `--width-breakout` (default 90ch)."
302
+ },
303
+ "spotlight": {
304
+ "type": "string",
305
+ "description": "`.spotlight` track → `--width-spotlight` (default 120ch)."
306
+ },
307
+ "nav": {
308
+ "type": "string",
309
+ "description": "Navigation column beside content → `--width-nav` (default 16rem)."
310
+ }
311
+ },
312
+ "additionalProperties": false,
313
+ "description": "Content track widths for `.centered`. In `ch` so the reading measure stays character-based; keep measure ≤ breakout ≤ spotlight."
314
+ },
315
+ "regionSpace": {
316
+ "type": "object",
317
+ "properties": {
318
+ "min": {
319
+ "type": "string",
320
+ "description": "Floor → `--region-space-min` (default 3rem)."
321
+ },
322
+ "preferred": {
323
+ "type": "string",
324
+ "description": "Preferred value → `--region-space` (default 8vh)."
325
+ },
326
+ "max": {
327
+ "type": "string",
328
+ "description": "Ceiling → `--region-space-max` (default 8rem)."
329
+ }
330
+ },
331
+ "additionalProperties": false,
332
+ "description": "Vertical padding of `.region`: `padding-block: clamp(min, preferred, max)`."
333
+ }
334
+ },
335
+ "additionalProperties": false,
336
+ "description": "Optional layout tokens. Each key you set is emitted as a `:root` custom property (css, bricks and tailwind formats); each you omit keeps the framework default. Lets the live editor tune widths and region spacing instead of a hand-written override stylesheet."
337
+ },
248
338
  "spaceScale": {
249
339
  "description": "Fluid modular SPACE scale → `--space-<name>` tokens, consumed by spacing/gap utilities and vertical rhythm.",
250
340
  "type": "object",
@@ -466,7 +556,7 @@
466
556
  "number"
467
557
  ]
468
558
  },
469
- "description": "A bag of CSS-ish keys, each mapped to a declaration plus a `--<role>-<sfx>` override hook. The recognised set is **closed**: `family`, `size`, `weight`, `style`, `line-height`, `tracking` (→ `letter-spacing`), `text-transform`, `text-decoration`, `text-wrap`, `color`. Note the last four are spelled with their full CSS property names — `transform` and `decoration` are NOT accepted. Anything unrecognised is **ignored**, not passed through, so the generator warns rather than emitting it: a silently-dropped `transform: uppercase` is how title-case navigation reaches production. Note also that `style`, `text-transform`, `text-decoration` and `text-wrap` are emitted on **every** role at their identity value (`normal`/`none`/`none`/`wrap`) whether declared or not, so applying one role class over another fully resets it — which means **omitting `text-wrap` is not \"inherit\"**: it emits `text-wrap: wrap` and cancels the `pretty` the role would otherwise inherit from a `pretty` ancestor such as a `body`-mapped role. Declare it on every role — `balance` for heading-like roles, `pretty` for copy, `wrap` for short single-line labels."
559
+ "description": "A bag of CSS-ish keys, each mapped to a declaration plus a `--<role>-<sfx>` override hook. The recognised set is **closed**: `family`, `size`, `weight`, `style`, `line-height`, `tracking` (→ `letter-spacing`), `text-transform`, `text-decoration`, `text-wrap`, `color`. The canonical spellings of the last four are their full CSS property names (`text-transform`, `text-decoration`, …); `transform` and `decoration` are accepted as aliases of the first two and normalised to them. Anything unrecognised is **ignored**, not passed through, so the generator warns rather than emitting it: a silently-dropped key (a typo for `text-transform`, say) is how title-case navigation reaches production. Note also that `style`, `text-transform`, `text-decoration` and `text-wrap` are emitted on **every** role at their identity value (`normal`/`none`/`none`/`wrap`) whether declared or not, so applying one role class over another fully resets it — which means **omitting `text-wrap` is not \"inherit\"**: it emits `text-wrap: wrap` and cancels the `pretty` the role would otherwise inherit from a `pretty` ancestor such as a `body`-mapped role. Declare it on every role — `balance` for heading-like roles, `pretty` for copy, `wrap` for short single-line labels."
470
560
  }
471
561
  },
472
562
  "headings": {
@@ -604,7 +694,7 @@
604
694
  "type": "string"
605
695
  },
606
696
  "defaultColorScheme": {
607
- "description": "Initial appearance. `\"system\"` follows the OS via `prefers-color-scheme` and is what makes `<wc-color-scheme-toggle>`'s \"System\" position resolve to anything — it removes the theme attribute, so without this the page falls through to light. It also gives a no-JS page the OS appearance. Defaults to `\"light\"`, because switching an existing site to `\"system\"` visibly flips it dark for dark-OS visitors.",
697
+ "description": "Initial appearance. `\"dark\"` makes the site DARK-ONLY: the dark tokens become the `:root` appearance (with `color-scheme: dark`), no light block or `data-theme` flip is emitted, and the light-mode contrast checks are skipped — so a palette that only works dark (bright fills with dark text, for example) builds. Do not ship `<wc-color-scheme-toggle>` on such a site. `\"system\"` follows the OS via `prefers-color-scheme` and is what makes `<wc-color-scheme-toggle>`'s \"System\" position resolve to anything — it removes the theme attribute, so without this the page falls through to light. It also gives a no-JS page the OS appearance. Defaults to `\"light\"`, because switching an existing site to `\"system\"` visibly flips it dark for dark-OS visitors.",
608
698
  "type": "string",
609
699
  "enum": [
610
700
  "light",
@@ -694,6 +784,7 @@
694
784
  "type": "object",
695
785
  "properties": {
696
786
  "streetAddress": {
787
+ "description": "Street line. Optional: a business with no public street address (home-based, service-area) omits it, and the generated legal documents and JSON-LD simply leave the line out.",
697
788
  "type": "string"
698
789
  },
699
790
  "addressLocality": {
@@ -713,12 +804,28 @@
713
804
  }
714
805
  },
715
806
  "required": [
716
- "streetAddress",
717
807
  "addressLocality",
718
808
  "addressCountry"
719
809
  ],
720
810
  "additionalProperties": false
721
811
  },
812
+ "description": {
813
+ "description": "One or two sentences on what the organization does → JSON-LD `description` and a fallback for SEO. Localisable.",
814
+ "anyOf": [
815
+ {
816
+ "type": "string"
817
+ },
818
+ {
819
+ "type": "object",
820
+ "propertyNames": {
821
+ "type": "string"
822
+ },
823
+ "additionalProperties": {
824
+ "type": "string"
825
+ }
826
+ }
827
+ ]
828
+ },
722
829
  "taxID": {
723
830
  "description": "Tax identification number.",
724
831
  "type": "string"
@@ -759,6 +866,7 @@
759
866
  "type": "object",
760
867
  "properties": {
761
868
  "streetAddress": {
869
+ "description": "Street line. Optional: a business with no public street address (home-based, service-area) omits it, and the generated legal documents and JSON-LD simply leave the line out.",
762
870
  "type": "string"
763
871
  },
764
872
  "addressLocality": {
@@ -778,7 +886,6 @@
778
886
  }
779
887
  },
780
888
  "required": [
781
- "streetAddress",
782
889
  "addressLocality",
783
890
  "addressCountry"
784
891
  ],
@@ -849,6 +956,7 @@
849
956
  "type": "object",
850
957
  "properties": {
851
958
  "streetAddress": {
959
+ "description": "Street line. Optional: a business with no public street address (home-based, service-area) omits it, and the generated legal documents and JSON-LD simply leave the line out.",
852
960
  "type": "string"
853
961
  },
854
962
  "addressLocality": {
@@ -868,7 +976,6 @@
868
976
  }
869
977
  },
870
978
  "required": [
871
- "streetAddress",
872
979
  "addressLocality",
873
980
  "addressCountry"
874
981
  ],
@@ -2954,7 +3061,8 @@
2954
3061
  "description": "Which legal template set the generated documents use. Default `ca`.",
2955
3062
  "type": "string",
2956
3063
  "enum": [
2957
- "ca"
3064
+ "ca",
3065
+ "qc"
2958
3066
  ]
2959
3067
  },
2960
3068
  "privacyPolicy": {
@@ -2995,6 +3103,7 @@
2995
3103
  "type": "object",
2996
3104
  "properties": {
2997
3105
  "streetAddress": {
3106
+ "description": "Street line. Optional: a business with no public street address (home-based, service-area) omits it, and the generated legal documents and JSON-LD simply leave the line out.",
2998
3107
  "type": "string"
2999
3108
  },
3000
3109
  "addressLocality": {
@@ -3014,7 +3123,6 @@
3014
3123
  }
3015
3124
  },
3016
3125
  "required": [
3017
- "streetAddress",
3018
3126
  "addressLocality",
3019
3127
  "addressCountry"
3020
3128
  ],
@@ -3026,6 +3134,14 @@
3026
3134
  }
3027
3135
  ]
3028
3136
  },
3137
+ "privacyOfficerTitle": {
3138
+ "description": "Title of the person in charge of the protection of personal information (e.g. \"President\"). Quebec Law 25 requires the title and contact details to be published; the `qc` templates print it beside the `privacyOfficer` contact. Not asserted when absent.",
3139
+ "type": "string"
3140
+ },
3141
+ "impactAssessments": {
3142
+ "description": "Attests that a privacy impact assessment is carried out before personal information is communicated outside Quebec (Law 25, s. 17). The `qc` privacy policy states that assurance only when this is `true` — a fact the config cannot otherwise know, so it is never assumed.",
3143
+ "type": "boolean"
3144
+ },
3029
3145
  "retention": {
3030
3146
  "description": "How long personal information is kept, in prose (e.g. \"24 months after last contact\").",
3031
3147
  "type": "string"