@servicetitan/hammer-token 2.5.2 → 3.0.1

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 (146) hide show
  1. package/CHANGELOG.md +52 -2
  2. package/README.md +332 -0
  3. package/build/web/core/component-variables.scss +1088 -131
  4. package/build/web/core/component.d.ts +558 -0
  5. package/build/web/core/component.js +6685 -249
  6. package/build/web/core/component.scss +557 -69
  7. package/build/web/core/css-utils/a2-border.css +23 -51
  8. package/build/web/core/css-utils/a2-color.css +221 -233
  9. package/build/web/core/css-utils/a2-font.css +1 -29
  10. package/build/web/core/css-utils/a2-spacing.css +238 -483
  11. package/build/web/core/css-utils/a2-utils.css +496 -781
  12. package/build/web/core/css-utils/border.css +23 -51
  13. package/build/web/core/css-utils/color.css +221 -233
  14. package/build/web/core/css-utils/font.css +1 -29
  15. package/build/web/core/css-utils/spacing.css +238 -483
  16. package/build/web/core/css-utils/utils.css +496 -781
  17. package/build/web/core/index.d.ts +6 -0
  18. package/build/web/core/index.js +1 -1
  19. package/build/web/core/primitive-variables.scss +148 -65
  20. package/build/web/core/primitive.d.ts +209 -0
  21. package/build/web/core/primitive.js +779 -61
  22. package/build/web/core/primitive.scss +207 -124
  23. package/build/web/core/semantic-variables.scss +363 -245
  24. package/build/web/core/semantic.d.ts +221 -0
  25. package/build/web/core/semantic.js +1592 -347
  26. package/build/web/core/semantic.scss +219 -140
  27. package/build/web/index.d.ts +3 -4
  28. package/build/web/types.d.ts +17 -0
  29. package/config.js +121 -496
  30. package/eslint.config.mjs +11 -1
  31. package/package.json +15 -5
  32. package/src/global/primitive/breakpoint.tokens.json +54 -0
  33. package/src/global/primitive/color.tokens.json +1092 -0
  34. package/src/global/primitive/duration.tokens.json +44 -0
  35. package/src/global/primitive/font.tokens.json +151 -0
  36. package/src/global/primitive/radius.tokens.json +94 -0
  37. package/src/global/primitive/size.tokens.json +174 -0
  38. package/src/global/primitive/transition.tokens.json +32 -0
  39. package/src/theme/core/background.tokens.json +1312 -0
  40. package/src/theme/core/border.tokens.json +192 -0
  41. package/src/theme/core/chart.tokens.json +982 -0
  42. package/src/theme/core/component/ai-mark.tokens.json +20 -0
  43. package/src/theme/core/component/alert.tokens.json +261 -0
  44. package/src/theme/core/component/announcement.tokens.json +460 -0
  45. package/src/theme/core/component/avatar.tokens.json +137 -0
  46. package/src/theme/core/component/badge.tokens.json +42 -0
  47. package/src/theme/core/component/breadcrumb.tokens.json +42 -0
  48. package/src/theme/core/component/button-toggle.tokens.json +428 -0
  49. package/src/theme/core/component/button.tokens.json +941 -0
  50. package/src/theme/core/component/calendar.tokens.json +391 -0
  51. package/src/theme/core/component/card.tokens.json +107 -0
  52. package/src/theme/core/component/checkbox.tokens.json +631 -0
  53. package/src/theme/core/component/chip.tokens.json +169 -0
  54. package/src/theme/core/component/combobox.tokens.json +269 -0
  55. package/src/theme/core/component/details.tokens.json +152 -0
  56. package/src/theme/core/component/dialog.tokens.json +87 -0
  57. package/src/theme/core/component/divider.tokens.json +23 -0
  58. package/src/theme/core/component/dnd.tokens.json +208 -0
  59. package/src/theme/core/component/drawer.tokens.json +61 -0
  60. package/src/theme/core/component/drilldown.tokens.json +61 -0
  61. package/src/theme/core/component/edit-card.tokens.json +381 -0
  62. package/src/theme/core/component/field-label.tokens.json +42 -0
  63. package/src/theme/core/component/field-message.tokens.json +65 -0
  64. package/src/theme/core/component/icon.tokens.json +42 -0
  65. package/src/theme/core/component/link.tokens.json +108 -0
  66. package/src/theme/core/component/list-view.tokens.json +82 -0
  67. package/src/theme/core/component/listbox.tokens.json +283 -0
  68. package/src/theme/core/component/menu.tokens.json +230 -0
  69. package/src/theme/core/component/overflow.tokens.json +84 -0
  70. package/src/theme/core/component/page.tokens.json +377 -0
  71. package/src/theme/core/component/pagination.tokens.json +63 -0
  72. package/src/theme/core/component/popover.tokens.json +122 -0
  73. package/src/theme/core/component/progress-bar.tokens.json +133 -0
  74. package/src/theme/core/component/radio.tokens.json +631 -0
  75. package/src/theme/core/component/segmented-control.tokens.json +175 -0
  76. package/src/theme/core/component/select-card.tokens.json +943 -0
  77. package/src/theme/core/component/side-nav.tokens.json +349 -0
  78. package/src/theme/core/component/skeleton.tokens.json +42 -0
  79. package/src/theme/core/component/spinner.tokens.json +96 -0
  80. package/src/theme/core/component/status-icon.tokens.json +164 -0
  81. package/src/theme/core/component/stepper.tokens.json +484 -0
  82. package/src/theme/core/component/switch.tokens.json +285 -0
  83. package/src/theme/core/component/tab.tokens.json +192 -0
  84. package/src/theme/core/component/text-field.tokens.json +160 -0
  85. package/src/theme/core/component/text.tokens.json +59 -0
  86. package/src/theme/core/component/toast.tokens.json +343 -0
  87. package/src/theme/core/component/toolbar.tokens.json +114 -0
  88. package/src/theme/core/component/tooltip.tokens.json +61 -0
  89. package/src/theme/core/focus.tokens.json +56 -0
  90. package/src/theme/core/foreground.tokens.json +416 -0
  91. package/src/theme/core/gradient.tokens.json +41 -0
  92. package/src/theme/core/opacity.tokens.json +25 -0
  93. package/src/theme/core/shadow.tokens.json +81 -0
  94. package/src/theme/core/status.tokens.json +74 -0
  95. package/src/theme/core/typography.tokens.json +163 -0
  96. package/src/utils/__tests__/css-utils-format-utils.test.js +312 -0
  97. package/src/utils/__tests__/sd-build-configs.test.js +306 -0
  98. package/src/utils/__tests__/sd-formats.test.js +942 -0
  99. package/src/utils/__tests__/sd-transforms.test.js +336 -0
  100. package/src/utils/__tests__/token-helpers.test.js +1160 -0
  101. package/src/utils/copy-css-utils-cli.js +13 -1
  102. package/src/utils/css-utils-format-utils.js +105 -176
  103. package/src/utils/figma/__tests__/sync-gradient.test.js +561 -0
  104. package/src/utils/figma/__tests__/token-conversion.test.js +117 -0
  105. package/src/utils/figma/__tests__/token-resolution.test.js +231 -0
  106. package/src/utils/figma/auth.js +355 -0
  107. package/src/utils/figma/constants.js +22 -0
  108. package/src/utils/figma/errors.js +80 -0
  109. package/src/utils/figma/figma-api.js +1069 -0
  110. package/src/utils/figma/get-token.js +348 -0
  111. package/src/utils/figma/sync-components.js +909 -0
  112. package/src/utils/figma/sync-main.js +692 -0
  113. package/src/utils/figma/sync-orchestration.js +683 -0
  114. package/src/utils/figma/sync-primitives.js +230 -0
  115. package/src/utils/figma/sync-semantic.js +1056 -0
  116. package/src/utils/figma/token-conversion.js +340 -0
  117. package/src/utils/figma/token-parsing.js +186 -0
  118. package/src/utils/figma/token-resolution.js +569 -0
  119. package/src/utils/figma/utils.js +199 -0
  120. package/src/utils/sd-build-configs.js +305 -0
  121. package/src/utils/sd-formats.js +948 -0
  122. package/src/utils/sd-transforms.js +165 -0
  123. package/src/utils/token-helpers.js +848 -0
  124. package/tsconfig.json +18 -0
  125. package/vitest.config.js +17 -0
  126. package/.turbo/turbo-build.log +0 -37
  127. package/build/web/core/raw.js +0 -234
  128. package/src/global/primitive/breakpoint.js +0 -19
  129. package/src/global/primitive/color.js +0 -231
  130. package/src/global/primitive/duration.js +0 -16
  131. package/src/global/primitive/font.js +0 -60
  132. package/src/global/primitive/radius.js +0 -31
  133. package/src/global/primitive/size.js +0 -55
  134. package/src/global/primitive/transition.js +0 -16
  135. package/src/theme/core/background.js +0 -170
  136. package/src/theme/core/border.js +0 -103
  137. package/src/theme/core/charts.js +0 -464
  138. package/src/theme/core/component/button.js +0 -708
  139. package/src/theme/core/component/checkbox.js +0 -405
  140. package/src/theme/core/focus.js +0 -35
  141. package/src/theme/core/foreground.js +0 -148
  142. package/src/theme/core/overlay.js +0 -137
  143. package/src/theme/core/shadow.js +0 -29
  144. package/src/theme/core/status.js +0 -49
  145. package/src/theme/core/typography.js +0 -82
  146. package/type/types.ts +0 -344
package/CHANGELOG.md CHANGED
@@ -1,10 +1,60 @@
1
1
  # @servicetitan/hammer-token
2
2
 
3
- ## 2.5.2
3
+ ## 3.0.1
4
4
 
5
5
  ### Patch Changes
6
6
 
7
- - [#2268](https://github.com/servicetitan/hammer/pull/2268) [`e085299`](https://github.com/servicetitan/hammer/commit/e085299f971a0856f2b230e89f03df0f2b0ee458) Thanks [@w-a-t-s-o-n](https://github.com/w-a-t-s-o-n)! - [Tokens] Drop broken runtime re-export from `build/web/index.js`. `Token` is type-only, so bundlers no longer fail resolving `../../type/types`.
7
+ - [#2289](https://github.com/servicetitan/hammer/pull/2289) [`9d9c1c3`](https://github.com/servicetitan/hammer/commit/9d9c1c3851ed9e6d51a7faaa782ae3d0e5a93313) Thanks [@w-a-t-s-o-n](https://github.com/w-a-t-s-o-n)! - [CSS Utils] Stop emitting legacy cascade `@layer` wrappers and duplicate `@layer application` blocks from `buildCssUtilsOutput`; keep optional `@supports` wrappers for dark-aware color utilities only.
8
+
9
+ ## 3.0.0
10
+
11
+ ### Major Changes
12
+
13
+ - [#1899](https://github.com/servicetitan/hammer/pull/1899) [`6ea319a`](https://github.com/servicetitan/hammer/commit/6ea319a282209312485756bfd37f1e2102f8c7e5) Thanks [@tounsoo](https://github.com/tounsoo)! - [Tokens] Renaming of interactive tokens for clarity and better typeahead support.
14
+
15
+ - [#1899](https://github.com/servicetitan/hammer/pull/1899) [`6ea319a`](https://github.com/servicetitan/hammer/commit/6ea319a282209312485756bfd37f1e2102f8c7e5) Thanks [@tounsoo](https://github.com/tounsoo)! - 3.0 Pre-release.
16
+
17
+ - [#1899](https://github.com/servicetitan/hammer/pull/1899) [`6ea319a`](https://github.com/servicetitan/hammer/commit/6ea319a282209312485756bfd37f1e2102f8c7e5) Thanks [@tounsoo](https://github.com/tounsoo)! - [Tokens] Chart stroke token is split into `stroke.color` and `fill.pattern` for clarity; chart category collections renamed from `ChartsCategorical`/`ChartsMonochrome`/`ChartsStatus` to `ChartCategorical`/`ChartMonochrome`/`ChartStatus`. Consumers of the ext-charts themes receive the new names automatically
18
+
19
+ - [#1899](https://github.com/servicetitan/hammer/pull/1899) [`6ea319a`](https://github.com/servicetitan/hammer/commit/6ea319a282209312485756bfd37f1e2102f8c7e5) Thanks [@tounsoo](https://github.com/tounsoo)! - [Tokens] JS import object changed to match DTCG format.
20
+
21
+ - [#1899](https://github.com/servicetitan/hammer/pull/1899) [`6ea319a`](https://github.com/servicetitan/hammer/commit/6ea319a282209312485756bfd37f1e2102f8c7e5) Thanks [@tounsoo](https://github.com/tounsoo)! - [Tokens] Prefix all CSS variables with `a2-` to prevent naming collisions (e.g., `--color-primary` becomes `--a2-color-primary`)
22
+
23
+ - [#1899](https://github.com/servicetitan/hammer/pull/1899) [`6ea319a`](https://github.com/servicetitan/hammer/commit/6ea319a282209312485756bfd37f1e2102f8c7e5) Thanks [@tounsoo](https://github.com/tounsoo)! - [Tokens] Renamed types exported for clarity of use.
24
+
25
+ ### Minor Changes
26
+
27
+ - [#1899](https://github.com/servicetitan/hammer/pull/1899) [`6ea319a`](https://github.com/servicetitan/hammer/commit/6ea319a282209312485756bfd37f1e2102f8c7e5) Thanks [@tounsoo](https://github.com/tounsoo)! - [Tokens] Update color ramp and add T3 component tokens for breadcrumb, button, buttonToggle, and link
28
+
29
+ - [#1899](https://github.com/servicetitan/hammer/pull/1899) [`6ea319a`](https://github.com/servicetitan/hammer/commit/6ea319a282209312485756bfd37f1e2102f8c7e5) Thanks [@tounsoo](https://github.com/tounsoo)! - [Tokens] Add `mauves` and `lime` primitive color palettes.
30
+
31
+ ### Patch Changes
32
+
33
+ - [#1899](https://github.com/servicetitan/hammer/pull/1899) [`6ea319a`](https://github.com/servicetitan/hammer/commit/6ea319a282209312485756bfd37f1e2102f8c7e5) Thanks [@tounsoo](https://github.com/tounsoo)! - [Tokens] Add Avatar component design tokens and migrate SCSS to use token variables.
34
+
35
+ - [#1899](https://github.com/servicetitan/hammer/pull/1899) [`6ea319a`](https://github.com/servicetitan/hammer/commit/6ea319a282209312485756bfd37f1e2102f8c7e5) Thanks [@tounsoo](https://github.com/tounsoo)! - [Tokens] Add Announcement component design tokens, missing foreground tokens for success, and migrate SCSS to use token variables.
36
+
37
+ - [#1899](https://github.com/servicetitan/hammer/pull/1899) [`6ea319a`](https://github.com/servicetitan/hammer/commit/6ea319a282209312485756bfd37f1e2102f8c7e5) Thanks [@tounsoo](https://github.com/tounsoo)! - [Tokens] Add `gradient.primary` semantic token and `ai-mark.primary.background.gradient` component token.
38
+
39
+ - [#1899](https://github.com/servicetitan/hammer/pull/1899) [`6ea319a`](https://github.com/servicetitan/hammer/commit/6ea319a282209312485756bfd37f1e2102f8c7e5) Thanks [@tounsoo](https://github.com/tounsoo)! - [Tokens][Menu] Add `menu.item` hover and active state tokens (`foreground.color-hover`, `foreground.color-active`, `background.color-active`) and wire them through Menu styles.
40
+
41
+ - [#1899](https://github.com/servicetitan/hammer/pull/1899) [`6ea319a`](https://github.com/servicetitan/hammer/commit/6ea319a282209312485756bfd37f1e2102f8c7e5) Thanks [@tounsoo](https://github.com/tounsoo)! - [Tokens] Add missing tokens and correct existing shapes for Listbox, ListView, Pagination, Stepper, and Toolbar component token files (Toolbar rebuilt from scratch).
42
+
43
+ - [#1899](https://github.com/servicetitan/hammer/pull/1899) [`6ea319a`](https://github.com/servicetitan/hammer/commit/6ea319a282209312485756bfd37f1e2102f8c7e5) Thanks [@tounsoo](https://github.com/tounsoo)! - [Tokens] Add Badge component design tokens and migrate SCSS to use token variables.
44
+
45
+ - [#1899](https://github.com/servicetitan/hammer/pull/1899) [`6ea319a`](https://github.com/servicetitan/hammer/commit/6ea319a282209312485756bfd37f1e2102f8c7e5) Thanks [@tounsoo](https://github.com/tounsoo)! - [Tokens][SideNav] Restructure SideNav tokens and update SideNav styles to match. Consumers referencing the prior SideNav token names must migrate to the new shape
46
+
47
+ - [#1899](https://github.com/servicetitan/hammer/pull/1899) [`6ea319a`](https://github.com/servicetitan/hammer/commit/6ea319a282209312485756bfd37f1e2102f8c7e5) Thanks [@tounsoo](https://github.com/tounsoo)! - [Tokens][Switch] Restructure Switch tokens (new hierarchy and shadow token scoping) and update Switch styles to match. Consumers referencing the prior Switch token names must migrate to the new shape
48
+
49
+ - [#1899](https://github.com/servicetitan/hammer/pull/1899) [`6ea319a`](https://github.com/servicetitan/hammer/commit/6ea319a282209312485756bfd37f1e2102f8c7e5) Thanks [@tounsoo](https://github.com/tounsoo)! - [Tokens] Consolidate TextField, Textarea, and SearchField tokens into a single `text-field` token set. `search-field.tokens.json` and `textarea.tokens.json` are removed; their tokens are merged into `text-field.tokens.json` with a flattened hierarchy and renames (e.g. `background-color-strong` → `background-color-disabled`). Consumers of the prior per-component token names must migrate
50
+
51
+ - [#1899](https://github.com/servicetitan/hammer/pull/1899) [`6ea319a`](https://github.com/servicetitan/hammer/commit/6ea319a282209312485756bfd37f1e2102f8c7e5) Thanks [@tounsoo](https://github.com/tounsoo)! - [Tokens] Add component tokens for Details, Dialog, Divider, Dnd, Drawer, and DrillDown
52
+
53
+ - [#1899](https://github.com/servicetitan/hammer/pull/1899) [`6ea319a`](https://github.com/servicetitan/hammer/commit/6ea319a282209312485756bfd37f1e2102f8c7e5) Thanks [@tounsoo](https://github.com/tounsoo)! - [Tokens] Use direct token references for button disabled colors; add calendar, opacity, card, checkbox, chip, and combobox component tokens.
54
+
55
+ - [#1899](https://github.com/servicetitan/hammer/pull/1899) [`6ea319a`](https://github.com/servicetitan/hammer/commit/6ea319a282209312485756bfd37f1e2102f8c7e5) Thanks [@tounsoo](https://github.com/tounsoo)! - [Tokens] Add component tokens for E-T components: EditCard, FieldLabel, FieldMessage, Icon, Link, ListView, Listbox, Menu, Overflow, Page, Pagination, Popover, ProgressBar, Radio, SearchField, SegmentedControl, SelectCard, SideNav, Skeleton, Spinner, Stepper, Switch, Tab, Text, TextField, Textarea, Toast, Toolbar, and Tooltip
56
+
57
+ - [#1899](https://github.com/servicetitan/hammer/pull/1899) [`6ea319a`](https://github.com/servicetitan/hammer/commit/6ea319a282209312485756bfd37f1e2102f8c7e5) Thanks [@tounsoo](https://github.com/tounsoo)! - [Tokens] Add Alert component design tokens and migrate SCSS to use token variables.
8
58
 
9
59
  ## 2.5.1
10
60
 
package/README.md ADDED
@@ -0,0 +1,332 @@
1
+ # @servicetitan/hammer-token
2
+
3
+ Design token system for the Hammer design system, built with [Style Dictionary v5](https://styledictionary.com/) and the [Design Tokens Community Group (DTCG) format](https://www.designtokens.org/tr/2025.10/format/).
4
+
5
+ ## Overview
6
+
7
+ This package transforms design tokens from JSON source files into multiple output formats for use across web applications. It generates JavaScript modules, SCSS variables, CSS utility classes, and TypeScript definitions to support both runtime and build-time token consumption.
8
+
9
+ ## Token Structure
10
+
11
+ Tokens follow the [Design Tokens Community Group (DTCG) format](https://www.designtokens.org/tr/2025.10/format/).
12
+
13
+ ### Primitive Color Token
14
+
15
+ Primitive tokens have a static value and declare their Figma variable scope via `$extensions["com.figma.scopes"]`. An empty array means no scope restriction (the variable appears in all pickers).
16
+
17
+ ```json
18
+ {
19
+ "$type": "color",
20
+ "$value": "#ffffff",
21
+ "$extensions": {
22
+ "com.figma.scopes": []
23
+ }
24
+ }
25
+ ```
26
+
27
+ ### Semantic Color Token (with dark mode)
28
+
29
+ Semantic tokens reference primitives and include light/dark appearance variants under `$extensions.appearance`. Both `light` and `dark` repeat the `$type` and use `$value`.
30
+
31
+ ```json
32
+ {
33
+ "$type": "color",
34
+ "$value": "{status.color.info}",
35
+ "$extensions": {
36
+ "appearance": {
37
+ "light": {
38
+ "$type": "color",
39
+ "$value": "{status.color.info}"
40
+ },
41
+ "dark": {
42
+ "$type": "color",
43
+ "$value": "{status.color.info}"
44
+ }
45
+ },
46
+ "com.figma.scopes": ["STROKE_COLOR"]
47
+ }
48
+ }
49
+ ```
50
+
51
+ ### Composite Color Token (color + alpha)
52
+
53
+ Used for colors that need an alpha channel. The `color` field is a reference to a primitive token; the build system emits `color-mix()` in CSS output to preserve the live primitive CSS variable.
54
+
55
+ ```json
56
+ {
57
+ "$type": "color",
58
+ "$value": {
59
+ "color": "{color.neutral.900}",
60
+ "alpha": 0.08
61
+ },
62
+ "$extensions": {
63
+ "appearance": {
64
+ "light": {
65
+ "$type": "color",
66
+ "$value": { "color": "{color.neutral.900}", "alpha": 0.08 }
67
+ },
68
+ "dark": {
69
+ "$type": "color",
70
+ "$value": { "color": "{color.neutral.0}", "alpha": 0.08 }
71
+ }
72
+ },
73
+ "com.figma.scopes": ["EFFECT_COLOR"]
74
+ }
75
+ }
76
+ ```
77
+
78
+ ### Dimension Token
79
+
80
+ Dimension tokens (sizes, radii, breakpoints) use a nested object for `$value` with `value` and `unit` fields.
81
+
82
+ ```json
83
+ {
84
+ "$type": "dimension",
85
+ "$value": {
86
+ "value": 0.375,
87
+ "unit": "rem"
88
+ },
89
+ "$extensions": {
90
+ "com.figma.scopes": ["CORNER_RADIUS"]
91
+ }
92
+ }
93
+ ```
94
+
95
+ ### The $root Pattern
96
+
97
+ The `$root` pattern allows a token group to have a default value while still containing sub-tokens (e.g. interactive states). A node with `$value` cannot normally also have children; `$root` bridges this by placing the default value one level deeper.
98
+
99
+ ```json
100
+ "primary": {
101
+ "$root": {
102
+ "$type": "color",
103
+ "$value": "{color.blue.500}"
104
+ },
105
+ "hover": {
106
+ "$type": "color",
107
+ "$value": "{color.blue.600}"
108
+ },
109
+ "active": {
110
+ "$type": "color",
111
+ "$value": "{color.blue.700}"
112
+ }
113
+ }
114
+ ```
115
+
116
+ You can reference the group directly as `{background.color.primary}` — the build system resolves it to the `.$root` token automatically. The `$root` segment is stripped from all generated names (e.g. `--a2-background-color-primary`, not `--a2-background-color-primary-root`).
117
+
118
+ ## Token Naming Conventions
119
+
120
+ 1. **Path to name**: JSON object paths become hyphen-separated names (CSS/SCSS) or PascalCase (JS exports).
121
+ 2. **`$root` segments**: Stripped from the path in all outputs.
122
+ 3. **State suffixes**: State names (`hover`, `active`) are included as-is in the hyphenated name and capitalized in PascalCase exports.
123
+
124
+ ## Build Output (`/build/web`)
125
+
126
+ All generated CSS variable names use the `a2-` prefix by default (e.g. `--a2-background-color-primary`).
127
+
128
+ The build process executes three sequential Style Dictionary builds — **Primitive → Theme (semantic) → Component** — and writes output to `/build/web`:
129
+
130
+ ```
131
+ build/web/
132
+ ├── index.js # Main entry point
133
+ ├── index.d.ts # TypeScript definitions
134
+ ├── types.d.ts # Core types (TokenObj, Token)
135
+ └── core/
136
+ ├── primitive.js # Primitive tokens (JS)
137
+ ├── primitive.scss # Primitive tokens (SCSS)
138
+ ├── primitive-variables.scss # Primitive tokens map (SCSS)
139
+ ├── primitive.d.ts # Primitive tokens (TypeScript)
140
+ ├── semantic.js # Semantic tokens (JS)
141
+ ├── semantic.scss # Semantic tokens (SCSS)
142
+ ├── semantic-variables.scss # Semantic tokens map (SCSS)
143
+ ├── semantic.d.ts # Semantic tokens (TypeScript)
144
+ ├── component.js # Component tokens (JS)
145
+ ├── component.scss # Component tokens (SCSS)
146
+ ├── component-variables.scss # Component tokens map (SCSS)
147
+ ├── component.d.ts # Component tokens (TypeScript)
148
+ ├── index.js # Core index
149
+ ├── index.d.ts # Core TypeScript definitions
150
+ └── css-utils/ # CSS utility classes
151
+ ```
152
+
153
+ ### File Types
154
+
155
+ #### `*.js` Files
156
+
157
+ ES6 named exports with static resolved values. Tokens with dark variants include an `extensions.appearance.dark.value` property.
158
+
159
+ ```javascript
160
+ import { BackgroundColorPrimary } from "@servicetitan/hammer-token/build/web/core/semantic";
161
+ // { value: "#0265dc", extensions: { appearance: { dark: { value: "#78bbfa" } } } }
162
+ ```
163
+
164
+ > **Caution**: Values are resolved at build time and do not respond to CSS variable changes at runtime. Use `*.scss` files when dynamic theming is needed.
165
+
166
+ #### `*.scss` Files
167
+
168
+ SCSS variables with `var(--a2-name, fallback)` syntax, supporting recursive reference chains and `light-dark()` for dark mode.
169
+
170
+ #### `*-variables.scss` Files
171
+
172
+ SCSS maps (`$light`, `$dark`, `$nonColor`) used by `ThemeProvider.module.scss`.
173
+
174
+ #### `.d.ts` Files
175
+
176
+ Auto-generated TypeScript definitions using the unified `TokenObj` type.
177
+
178
+ ```typescript
179
+ import { TokenObj } from "../types";
180
+ export declare const ButtonPrimaryBackgroundColor: TokenObj;
181
+ ```
182
+
183
+ ## Utility Files (`src/utils/`)
184
+
185
+ ### `token-helpers.js`
186
+
187
+ Core helpers for token value extraction, reference resolution, and CSS fallback building. Key points:
188
+
189
+ - **Smart `$root` resolution**: `resolveReference` automatically retries with `.$root` appended when a reference points to a group rather than a leaf token.
190
+ - **Memoized token map**: `buildTokenMap` caches an O(1) name→token `Map` per dictionary instance via `WeakMap`.
191
+ - **Composite colors**: `{ color, alpha }` tokens emit `color-mix(in srgb, var(--a2-name, #hex) N%, transparent)` in CSS contexts, preserving the live primitive CSS variable reference. Static contexts (JS exports, SCSS maps) fall back to hex8.
192
+ - **`buildFallbackWithRefs`**: Main entry point used by all formats. Builds recursive `var(--name, ...)` chains and inserts `light-dark()` at the level where light and dark values first diverge.
193
+
194
+ ### `sd-transforms.js`
195
+
196
+ Registers DTCG transforms and the `dtcg` transform group:
197
+
198
+ - **`dtcg/set-token-names`** _(preprocessor)_: Pre-sets `token.name` to the full hyphenated path before transforms run. Prevents false name-collision warnings for tokens with unresolvable references that skip the transform pipeline.
199
+ - **`dtcg/name`**, **`dtcg/value`**, **`dtcg/cubic-bezier`**, **`dtcg/color-opacity`**: Path normalization, dimension formatting, cubicBezier→CSS, and composite color pass-through.
200
+
201
+ ### `css-utils-format-utils.js`
202
+
203
+ Pure functions that generate CSS utility class strings — `generateBorderClasses`, `generateColorClasses`, `generateFontClasses`, `generateSpacingClasses`. Each accepts a pre-resolved `value` (which may already contain a `light-dark()` expression built by `buildFallbackWithRefs`) and an optional `prefix`.
204
+
205
+ ### `sd-formats.js`
206
+
207
+ Registers all custom Style Dictionary output formats:
208
+
209
+ - `custom/scss-variables` — SCSS variables with `var()` + `light-dark()` fallbacks.
210
+ - `custom/scss-variables-map` — SCSS maps (`$light`, `$dark`, `$nonColor` / `$token`) for `ThemeProvider.module.scss`.
211
+ - `custom/es6-variable` — ES6 named exports with static resolved values.
212
+ - `custom/CSSVariables` — `:root {}` block with CSS custom properties.
213
+ - `custom/CSSUtils/{prefix}All|Borders|Colors|Fonts|Spacing` — CSS utility class files (registered for both `""` and `"a2-"` prefixes).
214
+
215
+ The `All` format uses a single-pass loop over `allTokens` (one `buildFallbackWithRefs` call per token for the light value, a second only when a dark variant exists) feeding three output buckets. The dedicated `Borders`, `Colors`, `Fonts`, and `Spacing` formats use separate filter+map pipelines.
216
+
217
+ ## Figma Sync (`src/utils/figma/`)
218
+
219
+ Script to sync design tokens to Figma variables using the Figma REST API.
220
+
221
+ ### Features
222
+
223
+ - Syncs all tokens (primitives, semantic, component) to a single Figma variable collection
224
+ - Creates Light and Dark modes for appearance variants
225
+ - Resolves primitive token references to actual values
226
+ - Creates variable aliases for semantic/component tokens that reference other tokens
227
+ - Handles `$root` pattern by creating separate variables for root and state variants
228
+ - Uses path-based naming (e.g., `color/blue/500`, `background/color/primary`)
229
+ - Applies **Figma variable scopes** so variables only appear in the relevant UI pickers
230
+ - Only updates variables when values change; still sends scope-only updates when scopes need to be applied
231
+ - Handles rate limiting with automatic retries
232
+
233
+ ### Directory
234
+
235
+ - **`auth.js`** - Authentication and configuration
236
+ - **`constants.js`** - Figma file and collection constants
237
+ - **`errors.js`** - Custom error classes
238
+ - **`get-token.js`** - OAuth2 token helper script
239
+ - **`token-parsing.js`** - Token file loading, parsing, and flattening
240
+ - **`token-resolution.js`** - Reference resolution and dependency sorting
241
+ - **`token-conversion.js`** - Converting tokens to Figma format
242
+ - **`figma-api.js`** - Figma API requests, collections, and modes
243
+ - **`sync-primitives.js`** - Primitive token sync logic
244
+ - **`sync-semantic.js`** - Semantic token sync logic
245
+ - **`sync-components.js`** - Component token sync logic
246
+ - **`sync-orchestration.js`** - Theme sync orchestration
247
+ - **`sync-main.js`** - Main entry point and CLI
248
+ - **`utils.js`** - Shared utility functions
249
+
250
+ ### Variable Scopes
251
+
252
+ Figma variables can be scoped so they only show in certain property pickers (e.g. a color variable only in stroke color, or a dimension only in corner radius).
253
+
254
+ Scopes are defined directly on each token in `$extensions["com.figma.scopes"]` — an array of Figma scope names (e.g. `SHAPE_FILL`, `STROKE_COLOR`, `CORNER_RADIUS`, `FONT_SIZE`). The sync reads this field when creating or updating variables; scopes are deduplicated before sending.
255
+
256
+ To change which pickers a token appears in, edit `$extensions["com.figma.scopes"]` in the token file.
257
+
258
+ ### Commands
259
+
260
+ - `pnpm figma:sync` - Sync all tokens to Figma (default file)
261
+ - `pnpm figma:sync:file <fileKey>` - Sync tokens to a specific Figma file
262
+ - `pnpm figma:test` - Test Figma API access (default file)
263
+ - `pnpm figma:test:file <fileKey>` - Test access to a specific Figma file
264
+ - `pnpm figma:validate` - Validate token files without syncing
265
+ - `pnpm figma:get-token` - Interactive OAuth2 token helper script
266
+
267
+ **CLI Options:** `--file-key`/`-f`, `--dry-run`, `--verbose`/`-v`, `--full`, `--help`/`-h`
268
+
269
+ ### Authentication
270
+
271
+ Supports Personal Access Tokens (PAT) and OAuth2 refresh tokens. Configure via environment variables or `.figma-config.json` (repo root, gitignored).
272
+
273
+ **Environment variables:**
274
+
275
+ | Variable | Description |
276
+ | --------------------- | -------------------------- |
277
+ | `FIGMA_ACCESS_TOKEN` | PAT |
278
+ | `FIGMA_CLIENT_ID` | OAuth2 client ID |
279
+ | `FIGMA_CLIENT_SECRET` | OAuth2 client secret |
280
+ | `FIGMA_REFRESH_TOKEN` | OAuth2 refresh token |
281
+ | `FIGMA_FILE_KEY` | Optional file key override |
282
+
283
+ **`.figma-config.json`:**
284
+
285
+ ```json
286
+ {
287
+ "accessToken": "figd_...",
288
+ "clientId": "your-oauth-client-id",
289
+ "clientSecret": "your-oauth-client-secret",
290
+ "refreshToken": "your-oauth-refresh-token"
291
+ }
292
+ ```
293
+
294
+ Environment variables take priority over the config file. OAuth2 access tokens are cached in memory and refreshed automatically on expiry (~1 hour).
295
+
296
+ **GitHub Actions:**
297
+
298
+ ```yaml
299
+ - name: Sync tokens to Figma
300
+ env:
301
+ FIGMA_CLIENT_ID: ${{ secrets.FIGMA_CLIENT_ID }}
302
+ FIGMA_CLIENT_SECRET: ${{ secrets.FIGMA_CLIENT_SECRET }}
303
+ FIGMA_REFRESH_TOKEN: ${{ secrets.FIGMA_REFRESH_TOKEN }}
304
+ run: pnpm figma:sync
305
+ ```
306
+
307
+ **Dry-run mode** (`--dry-run`): validates and reads existing variables without writing. Reports counts of what would be created/updated/skipped.
308
+
309
+ **Troubleshooting:**
310
+
311
+ - **Auth errors**: Verify credentials. For OAuth2, re-authenticate if refresh token has expired.
312
+ - **"Authentication Failed - Please Re-Login"**: OAuth2 refresh token expired or revoked.
313
+ - **403 Forbidden**: Token may lack organization-level access.
314
+ - **File not found**: Check the file key and access permissions.
315
+ - **Rate limiting**: Retried automatically with exponential backoff.
316
+ - **Refresh token rotation**: Update credentials with the new token logged to stdout.
317
+ - Run `pnpm figma:test` to diagnose issues before syncing; `pnpm figma:validate` to check token structure without API calls.
318
+
319
+ ## Development
320
+
321
+ ### Adding New Tokens
322
+
323
+ 1. Add token JSON files to `src/global/primitive/` (primitives) or `src/theme/core/` (semantic/component)
324
+ 2. Run `pnpm build` to regenerate output files
325
+ 3. Import tokens in your code using the generated files
326
+
327
+ ### Modifying Build Output
328
+
329
+ - **Transforms**: Edit `src/utils/sd-transforms.js`
330
+ - **Formats**: Edit `src/utils/sd-formats.js`
331
+ - **Build Configs**: Edit `src/utils/sd-build-configs.js`
332
+ - **CSS Utils**: Edit `src/utils/css-utils-format-utils.js`