okchroma 0.7.0 → 0.8.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.
package/README.md CHANGED
@@ -63,7 +63,9 @@ example: [Install and API](https://egerrity.github.io/okchroma/#/docs/install).
63
63
  Every token has one path, and every output spells it: `brand/stamp/fill`,
64
64
  `neutral/paper-0`, `link/default/enabled`, `absolute/brand`. Joined with hyphens it is the
65
65
  CSS custom property (`--brand-stamp-fill`); joined with slashes it is the Figma variable
66
- and the DTCG token path.
66
+ and the DTCG token path. A consumer whose paths start with the category puts a `color`
67
+ group in front: the extended plugin writes `color/brand/stamp/fill`, and the DTCG
68
+ documents nest under the same word when asked. The CSS names never carry it.
67
69
 
68
70
  | Group | Tokens |
69
71
  |---|---|
@@ -101,7 +103,8 @@ component renders the border unconditionally and layout never shifts.
101
103
  every token with `$type`, an sRGB `$value` whose components and hex are the same 8-bit
102
104
  color (or an alias where the CSS writes a reference), and a `$description`. The two join
103
105
  through a resolver document. The format: [docs/schema.md](docs/schema.md). The repo's
104
- `npm run tokens:emit -- '#E93D82' acme` writes both files.
106
+ `npm run tokens:emit -- '#E93D82' acme` writes both files. Pass `{ rootGroup: 'color' }`,
107
+ or `--root color` to the script, to nest every path and alias under that group.
105
108
  - Figma: `themeToFigma` returns a light and a dark group tree on the same paths; the
106
109
  extended plugin writes it into a file.
107
110
 
@@ -22,6 +22,7 @@ var index_exports = {};
22
22
  __export(index_exports, {
23
23
  ABSOLUTE_GROUP: () => ABSOLUTE_GROUP,
24
24
  BAND_STOPS: () => BAND_STOPS,
25
+ COLOR_GROUP: () => COLOR_GROUP,
25
26
  CSS_FAMILY: () => CSS_FAMILY,
26
27
  DEFAULT_LINK_HEX: () => DEFAULT_LINK_HEX,
27
28
  GUARANTEE_SCOPE: () => GUARANTEE_SCOPE,
@@ -865,6 +866,7 @@ var LINK_STATES = ["enabled", "hover", "pressed"];
865
866
  var linkPath = (posture, state) => [LINK_GROUP, posture, state];
866
867
  var ABSOLUTE_GROUP = "absolute";
867
868
  var absolutePath = (family) => [ABSOLUTE_GROUP, family];
869
+ var COLOR_GROUP = "color";
868
870
  var TOKEN_ORDER = [
869
871
  ...Object.values(SHARED_NAMES),
870
872
  STAMP_FILL,
@@ -2911,6 +2913,7 @@ var ZONE_MAP = [
2911
2913
  ["system/abs-alt", "absolute/brand-alt"],
2912
2914
  ["system/abs-primary", "absolute/brand"],
2913
2915
  ["system/link/", "link/"],
2916
+ ["color/", ""],
2914
2917
  ["base/", ""],
2915
2918
  ["primitive/", ""]
2916
2919
  ];
@@ -4050,7 +4053,11 @@ function dtcgColor(value) {
4050
4053
  throw new Error(`dtcgColor: not a color the emitters write: ${value}`);
4051
4054
  }
4052
4055
  var ALIAS = /^var\(--([a-z0-9-]+)\)$/;
4053
- function tokensToDtcg(tokens) {
4056
+ var SEGMENT = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
4057
+ function tokensToDtcg(tokens, options = {}) {
4058
+ const { rootGroup } = options;
4059
+ if (rootGroup !== void 0 && !SEGMENT.test(rootGroup)) throw new Error(`tokensToDtcg: rootGroup must be lower-case words and digits joined by hyphens: ${JSON.stringify(rootGroup)}`);
4060
+ const rooted = (path) => rootGroup === void 0 ? path : [rootGroup, ...path];
4054
4061
  const paths = byName();
4055
4062
  const roster = new Set(paths.keys());
4056
4063
  for (const name of tokens.names) if (!roster.has(name)) throw new Error(`tokensToDtcg: the emit carries a name the roster does not know: ${name}`);
@@ -4064,14 +4071,14 @@ function tokensToDtcg(tokens) {
4064
4071
  if (alias) {
4065
4072
  const target = paths.get(alias[1]);
4066
4073
  if (!target) throw new Error(`tokensToDtcg: ${name} references a name outside the roster: ${alias[1]}`);
4067
- token = { $type: "color", $value: `{${target.join(".")}}` };
4074
+ token = { $type: "color", $value: `{${rooted(target).join(".")}}` };
4068
4075
  } else {
4069
4076
  token = { $type: "color", $value: dtcgColor(tokens[mode][name]) };
4070
4077
  }
4071
4078
  const body = describeDocument(figmaPathOf(path));
4072
4079
  if (body) token.$description = body;
4073
4080
  let cur = doc;
4074
- for (const seg of path.slice(0, -1)) {
4081
+ for (const seg of rooted(path).slice(0, -1)) {
4075
4082
  const next = cur[seg];
4076
4083
  if (next && "$type" in next) throw new Error(`tokensToDtcg: ${seg} is both a token and a group on the way to ${path.join("/")}`);
4077
4084
  cur = cur[seg] ?? (cur[seg] = {});
@@ -773,6 +773,7 @@ var LINK_STATES = ["enabled", "hover", "pressed"];
773
773
  var linkPath = (posture, state) => [LINK_GROUP, posture, state];
774
774
  var ABSOLUTE_GROUP = "absolute";
775
775
  var absolutePath = (family) => [ABSOLUTE_GROUP, family];
776
+ var COLOR_GROUP = "color";
776
777
  var TOKEN_ORDER = [
777
778
  ...Object.values(SHARED_NAMES),
778
779
  STAMP_FILL,
@@ -2819,6 +2820,7 @@ var ZONE_MAP = [
2819
2820
  ["system/abs-alt", "absolute/brand-alt"],
2820
2821
  ["system/abs-primary", "absolute/brand"],
2821
2822
  ["system/link/", "link/"],
2823
+ ["color/", ""],
2822
2824
  ["base/", ""],
2823
2825
  ["primitive/", ""]
2824
2826
  ];
@@ -3958,7 +3960,11 @@ function dtcgColor(value) {
3958
3960
  throw new Error(`dtcgColor: not a color the emitters write: ${value}`);
3959
3961
  }
3960
3962
  var ALIAS = /^var\(--([a-z0-9-]+)\)$/;
3961
- function tokensToDtcg(tokens) {
3963
+ var SEGMENT = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
3964
+ function tokensToDtcg(tokens, options = {}) {
3965
+ const { rootGroup } = options;
3966
+ if (rootGroup !== void 0 && !SEGMENT.test(rootGroup)) throw new Error(`tokensToDtcg: rootGroup must be lower-case words and digits joined by hyphens: ${JSON.stringify(rootGroup)}`);
3967
+ const rooted = (path) => rootGroup === void 0 ? path : [rootGroup, ...path];
3962
3968
  const paths = byName();
3963
3969
  const roster = new Set(paths.keys());
3964
3970
  for (const name of tokens.names) if (!roster.has(name)) throw new Error(`tokensToDtcg: the emit carries a name the roster does not know: ${name}`);
@@ -3972,14 +3978,14 @@ function tokensToDtcg(tokens) {
3972
3978
  if (alias) {
3973
3979
  const target = paths.get(alias[1]);
3974
3980
  if (!target) throw new Error(`tokensToDtcg: ${name} references a name outside the roster: ${alias[1]}`);
3975
- token = { $type: "color", $value: `{${target.join(".")}}` };
3981
+ token = { $type: "color", $value: `{${rooted(target).join(".")}}` };
3976
3982
  } else {
3977
3983
  token = { $type: "color", $value: dtcgColor(tokens[mode][name]) };
3978
3984
  }
3979
3985
  const body = describeDocument(figmaPathOf(path));
3980
3986
  if (body) token.$description = body;
3981
3987
  let cur = doc;
3982
- for (const seg of path.slice(0, -1)) {
3988
+ for (const seg of rooted(path).slice(0, -1)) {
3983
3989
  const next = cur[seg];
3984
3990
  if (next && "$type" in next) throw new Error(`tokensToDtcg: ${seg} is both a token and a group on the way to ${path.join("/")}`);
3985
3991
  cur = cur[seg] ?? (cur[seg] = {});
@@ -3995,6 +4001,7 @@ function tokensToDtcg(tokens) {
3995
4001
  export {
3996
4002
  ABSOLUTE_GROUP,
3997
4003
  BAND_STOPS,
4004
+ COLOR_GROUP,
3998
4005
  CSS_FAMILY,
3999
4006
  DEFAULT_LINK_HEX,
4000
4007
  GUARANTEE_SCOPE,
@@ -28,12 +28,20 @@ export declare function tokenPathOf(name: string): TokenPath | undefined;
28
28
  export declare function descriptionPathOf(name: string): string | undefined;
29
29
  /** a resolved CSS value (hex, rgba(), transparent) as a DTCG color value */
30
30
  export declare function dtcgColor(value: string): DtcgColorValue;
31
+ export type DtcgOptions = {
32
+ /**
33
+ * A group to nest every path under, for a consumer whose grammar starts a path with its
34
+ * category (`color`, the word `COLOR_GROUP` holds). Aliases are written with it
35
+ * (`{color.brand.pencil-47}`). Omitted, the grammar's groups sit at the document root.
36
+ */
37
+ rootGroup?: string;
38
+ };
31
39
  /**
32
40
  * The two DTCG documents for a structured emit. Every primitive in the roster must be
33
41
  * present in the emit and nothing else may be; a missing or foreign name throws, so the
34
42
  * emit and the roster cannot drift apart silently.
35
43
  */
36
- export declare function tokensToDtcg(tokens: ThemeTokens): {
44
+ export declare function tokensToDtcg(tokens: ThemeTokens, options?: DtcgOptions): {
37
45
  light: DtcgDocument;
38
46
  dark: DtcgDocument;
39
47
  };
@@ -28,5 +28,6 @@ export type LinkState = (typeof LINK_STATES)[number];
28
28
  export declare const linkPath: (posture: LinkPosture, state: LinkState) => string[];
29
29
  export declare const ABSOLUTE_GROUP = "absolute";
30
30
  export declare const absolutePath: (family: string) => string[];
31
+ export declare const COLOR_GROUP = "color";
31
32
  export declare const EXT_OVERRIDABLE_SYSTEM: (p: string) => boolean;
32
33
  export declare function tokenOrder(name: string): number;
@@ -4,9 +4,9 @@ export { brandCss, neutralCss, signalsCss, stopsToVars, toHex, stopHex, OFFSET_A
4
4
  export { CSS_FAMILY, describeToken, describeDocument, GUARANTEE_SCOPE, BAND_STOPS } from './engine/tokenDescriptions';
5
5
  export { themeTokens, tokensFromEmission, readEmission, resolveReferences, type ThemeTokens, type ThemeTokensInput, type TokenMode, } from './engine/tokensRender';
6
6
  export { themeToFigma, groupEntries, type FigmaGroup, type FigmaColorToken, type FigmaLeaf, type ThemeInput, } from './engine/figmaRender';
7
- export { tokensToDtcg, tokenPathOf, descriptionPathOf, type DtcgDocument, type DtcgGroup, type DtcgToken, type DtcgColorValue, } from './engine/dtcgRender';
7
+ export { tokensToDtcg, tokenPathOf, descriptionPathOf, type DtcgDocument, type DtcgGroup, type DtcgToken, type DtcgColorValue, type DtcgOptions, } from './engine/dtcgRender';
8
8
  export { MODE_SPECS, type ModeSpec } from './engine/requirements/spec';
9
- export { stopTokenName, tokenOrder, SCALE_STOP_COUNT, PAPER_0, PEN_100, STAMP_FILL, STAMP_FILL_HOVER, STAMP_FILL_PRESSED, STAMP_EDGE, STAMP_ON, STAMP_STATE_LEAVES, STAMP_LEAF, cssVarName, figmaPathOf, familyPath, linkPath, absolutePath, LINK_GROUP, LINK_POSTURES, LINK_STATES, ABSOLUTE_GROUP, type TokenPath, type LinkPosture, type LinkState, } from './engine/tokenNames';
9
+ export { stopTokenName, tokenOrder, SCALE_STOP_COUNT, PAPER_0, PEN_100, STAMP_FILL, STAMP_FILL_HOVER, STAMP_FILL_PRESSED, STAMP_EDGE, STAMP_ON, STAMP_STATE_LEAVES, STAMP_LEAF, cssVarName, figmaPathOf, familyPath, linkPath, absolutePath, LINK_GROUP, LINK_POSTURES, LINK_STATES, ABSOLUTE_GROUP, COLOR_GROUP, type TokenPath, type LinkPosture, type LinkState, } from './engine/tokenNames';
10
10
  export { SIGNAL_EMIT_NAME } from './engine/signals';
11
11
  export { classifyArchetype, type Archetype } from './engine/archetypes';
12
12
  export { SIGNALS, type SignalDef } from './engine/signals';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "okchroma",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "license": "MIT",
5
5
  "description": "Color-system engine: one brand hex in, a light and dark set of color primitives out, with the contrast requirements solved during generation; emitted as CSS custom properties, DTCG documents, and Figma variables",
6
6
  "repository": {