@dialpad/dialtone-css 8.80.0-next.2 → 8.80.0-next.4

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 (187) hide show
  1. package/lib/build/js/dialtone_migrate_link_rendering/button-nav-test-examples.vue +92 -0
  2. package/lib/build/js/dialtone_migrate_link_rendering/button-nav.test.mjs +272 -0
  3. package/lib/build/js/dialtone_migrate_link_rendering/helpers.mjs +25 -0
  4. package/lib/build/js/dialtone_migrate_link_rendering/index.mjs +1041 -0
  5. package/lib/build/js/dialtone_migrate_link_rendering/link-nav-test-examples.vue +97 -0
  6. package/lib/build/js/dialtone_migrate_link_rendering/link-nav.test.mjs +194 -0
  7. package/lib/build/js/dialtone_migrate_link_rendering/underline-test-examples.vue +57 -0
  8. package/lib/build/js/dialtone_migrate_link_rendering/underline.test.mjs +161 -0
  9. package/lib/build/js/dialtone_migrate_props/index.mjs +794 -0
  10. package/lib/build/js/dialtone_migrate_props/test.mjs +959 -0
  11. package/lib/build/js/dialtone_migration_helper/configs/base-to-semantic.mjs +8 -8
  12. package/lib/build/js/dialtone_migration_helper/configs/size-to-layout.mjs +10 -0
  13. package/lib/build/js/dialtone_migration_helper/configs/success-to-positive.mjs +73 -0
  14. package/lib/build/js/dialtone_migration_helper/configs/utility-class-to-token-stops.mjs +92 -12
  15. package/lib/build/js/dialtone_migration_helper/tests/base-to-semantic-test-examples.vue +10 -10
  16. package/lib/build/js/dialtone_migration_helper/tests/base-to-semantic.test.mjs +8 -8
  17. package/lib/build/js/dialtone_migration_helper/tests/size-to-layout-test-examples.vue +16 -0
  18. package/lib/build/js/dialtone_migration_helper/tests/size-to-layout.test.mjs +87 -0
  19. package/lib/build/js/dialtone_migration_helper/tests/success-to-positive-test-examples.vue +166 -0
  20. package/lib/build/js/dialtone_migration_helper/tests/success-to-positive.test.mjs +287 -0
  21. package/lib/build/js/dialtone_migration_helper/tests/utility-class-to-token-stops-radius-examples.vue +66 -0
  22. package/lib/build/js/dialtone_migration_helper/tests/utility-class-to-token-stops.test.mjs +170 -0
  23. package/lib/build/less/components/badge.less +1 -1
  24. package/lib/build/less/components/banner.less +1 -1
  25. package/lib/build/less/components/box.less +9 -22
  26. package/lib/build/less/components/description-list.less +4 -0
  27. package/lib/build/less/components/forms.less +4 -2
  28. package/lib/build/less/components/input.less +2 -2
  29. package/lib/build/less/components/link.less +18 -4
  30. package/lib/build/less/components/modal.less +1 -1
  31. package/lib/build/less/components/notice.less +3 -3
  32. package/lib/build/less/components/progress_circle.less +10 -2
  33. package/lib/build/less/components/prose.less +512 -0
  34. package/lib/build/less/components/rich-text-editor.less +31 -0
  35. package/lib/build/less/components/selects.less +1 -1
  36. package/lib/build/less/components/text.less +2 -0
  37. package/lib/build/less/components/toast.less +1 -1
  38. package/lib/build/less/dialtone.less +1 -0
  39. package/lib/build/less/recipes/leftbar_row.less +2 -2
  40. package/lib/build/less/recipes/settings_menu_button.less +1 -1
  41. package/lib/build/less/recipes/top_banner_info.less +1 -1
  42. package/lib/build/less/utilities/backgrounds.less +12 -0
  43. package/lib/build/less/utilities/borders.less +56 -89
  44. package/lib/build/less/utilities/colors.less +8 -0
  45. package/lib/build/less/utilities/effects.less +1 -0
  46. package/lib/build/less/utilities/flex.less +145 -18
  47. package/lib/build/less/utilities/grid.less +40 -152
  48. package/lib/build/less/utilities/layout.less +19 -7
  49. package/lib/build/less/utilities/sizing.less +148 -143
  50. package/lib/build/less/variables/visual-styles.less +2 -1
  51. package/lib/dist/dialtone-default-theme.css +2840 -1807
  52. package/lib/dist/dialtone-default-theme.min.css +1 -1
  53. package/lib/dist/dialtone-docs.json +1 -1
  54. package/lib/dist/dialtone.css +2747 -1756
  55. package/lib/dist/dialtone.min.css +1 -1
  56. package/lib/dist/js/dialtone_migrate_link_rendering/button-nav-test-examples.vue +92 -0
  57. package/lib/dist/js/dialtone_migrate_link_rendering/button-nav.test.mjs +272 -0
  58. package/lib/dist/js/dialtone_migrate_link_rendering/helpers.mjs +25 -0
  59. package/lib/dist/js/dialtone_migrate_link_rendering/index.mjs +1041 -0
  60. package/lib/dist/js/dialtone_migrate_link_rendering/link-nav-test-examples.vue +97 -0
  61. package/lib/dist/js/dialtone_migrate_link_rendering/link-nav.test.mjs +194 -0
  62. package/lib/dist/js/dialtone_migrate_link_rendering/underline-test-examples.vue +57 -0
  63. package/lib/dist/js/dialtone_migrate_link_rendering/underline.test.mjs +161 -0
  64. package/lib/dist/js/dialtone_migrate_props/index.mjs +794 -0
  65. package/lib/dist/js/dialtone_migrate_props/test.mjs +959 -0
  66. package/lib/dist/js/dialtone_migration_helper/configs/base-to-semantic.mjs +8 -8
  67. package/lib/dist/js/dialtone_migration_helper/configs/size-to-layout.mjs +10 -0
  68. package/lib/dist/js/dialtone_migration_helper/configs/success-to-positive.mjs +73 -0
  69. package/lib/dist/js/dialtone_migration_helper/configs/utility-class-to-token-stops.mjs +92 -12
  70. package/lib/dist/js/dialtone_migration_helper/tests/base-to-semantic-test-examples.vue +10 -10
  71. package/lib/dist/js/dialtone_migration_helper/tests/base-to-semantic.test.mjs +8 -8
  72. package/lib/dist/js/dialtone_migration_helper/tests/size-to-layout-test-examples.vue +16 -0
  73. package/lib/dist/js/dialtone_migration_helper/tests/size-to-layout.test.mjs +87 -0
  74. package/lib/dist/js/dialtone_migration_helper/tests/success-to-positive-test-examples.vue +166 -0
  75. package/lib/dist/js/dialtone_migration_helper/tests/success-to-positive.test.mjs +287 -0
  76. package/lib/dist/js/dialtone_migration_helper/tests/utility-class-to-token-stops-radius-examples.vue +66 -0
  77. package/lib/dist/js/dialtone_migration_helper/tests/utility-class-to-token-stops.test.mjs +170 -0
  78. package/lib/dist/tokens/tokens-101-dark.css +81 -45
  79. package/lib/dist/tokens/tokens-101-light.css +75 -39
  80. package/lib/dist/tokens/tokens-102-dark.css +81 -45
  81. package/lib/dist/tokens/tokens-102-light.css +75 -39
  82. package/lib/dist/tokens/tokens-103-dark.css +81 -45
  83. package/lib/dist/tokens/tokens-103-light.css +75 -39
  84. package/lib/dist/tokens/tokens-104-dark.css +81 -45
  85. package/lib/dist/tokens/tokens-104-light.css +75 -39
  86. package/lib/dist/tokens/tokens-105-dark.css +81 -45
  87. package/lib/dist/tokens/tokens-105-light.css +75 -39
  88. package/lib/dist/tokens/tokens-106-dark.css +81 -45
  89. package/lib/dist/tokens/tokens-106-light.css +75 -39
  90. package/lib/dist/tokens/tokens-107-dark.css +81 -45
  91. package/lib/dist/tokens/tokens-107-light.css +75 -39
  92. package/lib/dist/tokens/tokens-108-dark.css +81 -45
  93. package/lib/dist/tokens/tokens-108-light.css +75 -39
  94. package/lib/dist/tokens/tokens-109-dark.css +81 -45
  95. package/lib/dist/tokens/tokens-109-light.css +75 -39
  96. package/lib/dist/tokens/tokens-110-dark.css +81 -45
  97. package/lib/dist/tokens/tokens-110-light.css +75 -39
  98. package/lib/dist/tokens/tokens-111-dark.css +81 -45
  99. package/lib/dist/tokens/tokens-111-light.css +75 -39
  100. package/lib/dist/tokens/tokens-112-dark.css +81 -45
  101. package/lib/dist/tokens/tokens-112-light.css +75 -39
  102. package/lib/dist/tokens/tokens-113-dark.css +81 -45
  103. package/lib/dist/tokens/tokens-113-light.css +75 -39
  104. package/lib/dist/tokens/tokens-114-dark.css +81 -45
  105. package/lib/dist/tokens/tokens-114-light.css +75 -39
  106. package/lib/dist/tokens/tokens-115-dark.css +81 -45
  107. package/lib/dist/tokens/tokens-115-light.css +75 -39
  108. package/lib/dist/tokens/tokens-116-dark.css +81 -45
  109. package/lib/dist/tokens/tokens-116-light.css +75 -39
  110. package/lib/dist/tokens/tokens-117-dark.css +81 -45
  111. package/lib/dist/tokens/tokens-117-light.css +75 -39
  112. package/lib/dist/tokens/tokens-118-dark.css +81 -45
  113. package/lib/dist/tokens/tokens-118-light.css +75 -39
  114. package/lib/dist/tokens/tokens-119-dark.css +81 -45
  115. package/lib/dist/tokens/tokens-119-light.css +75 -39
  116. package/lib/dist/tokens/tokens-120-dark.css +81 -45
  117. package/lib/dist/tokens/tokens-120-light.css +75 -39
  118. package/lib/dist/tokens/tokens-121-dark.css +81 -45
  119. package/lib/dist/tokens/tokens-121-light.css +75 -39
  120. package/lib/dist/tokens/tokens-122-dark.css +81 -45
  121. package/lib/dist/tokens/tokens-122-light.css +75 -39
  122. package/lib/dist/tokens/tokens-123-dark.css +81 -45
  123. package/lib/dist/tokens/tokens-123-light.css +75 -39
  124. package/lib/dist/tokens/tokens-124-dark.css +81 -45
  125. package/lib/dist/tokens/tokens-124-light.css +75 -39
  126. package/lib/dist/tokens/tokens-125-dark.css +81 -45
  127. package/lib/dist/tokens/tokens-125-light.css +75 -39
  128. package/lib/dist/tokens/tokens-126-dark.css +81 -45
  129. package/lib/dist/tokens/tokens-126-light.css +75 -39
  130. package/lib/dist/tokens/tokens-127-dark.css +81 -45
  131. package/lib/dist/tokens/tokens-127-light.css +75 -39
  132. package/lib/dist/tokens/tokens-128-dark.css +81 -45
  133. package/lib/dist/tokens/tokens-128-light.css +75 -39
  134. package/lib/dist/tokens/tokens-129-dark.css +81 -45
  135. package/lib/dist/tokens/tokens-129-light.css +75 -39
  136. package/lib/dist/tokens/tokens-130-dark.css +81 -45
  137. package/lib/dist/tokens/tokens-130-light.css +75 -39
  138. package/lib/dist/tokens/tokens-131-dark.css +81 -45
  139. package/lib/dist/tokens/tokens-131-light.css +75 -39
  140. package/lib/dist/tokens/tokens-132-dark.css +81 -45
  141. package/lib/dist/tokens/tokens-132-light.css +75 -39
  142. package/lib/dist/tokens/tokens-133-dark.css +81 -45
  143. package/lib/dist/tokens/tokens-133-light.css +75 -39
  144. package/lib/dist/tokens/tokens-134-dark.css +81 -45
  145. package/lib/dist/tokens/tokens-134-light.css +75 -39
  146. package/lib/dist/tokens/tokens-135-dark.css +81 -45
  147. package/lib/dist/tokens/tokens-135-light.css +75 -39
  148. package/lib/dist/tokens/tokens-136-dark.css +81 -45
  149. package/lib/dist/tokens/tokens-136-light.css +75 -39
  150. package/lib/dist/tokens/tokens-137-dark.css +81 -45
  151. package/lib/dist/tokens/tokens-137-light.css +75 -39
  152. package/lib/dist/tokens/tokens-aegean-dark.css +81 -45
  153. package/lib/dist/tokens/tokens-aegean-light.css +75 -39
  154. package/lib/dist/tokens/tokens-base-dark.css +18 -12
  155. package/lib/dist/tokens/tokens-base-light.css +18 -12
  156. package/lib/dist/tokens/tokens-botany-dark.css +81 -45
  157. package/lib/dist/tokens/tokens-botany-light.css +75 -39
  158. package/lib/dist/tokens/tokens-buttercream-dark.css +81 -45
  159. package/lib/dist/tokens/tokens-buttercream-light.css +75 -39
  160. package/lib/dist/tokens/tokens-ceruleo-dark.css +81 -45
  161. package/lib/dist/tokens/tokens-ceruleo-light.css +75 -39
  162. package/lib/dist/tokens/tokens-debug-base.css +6 -0
  163. package/lib/dist/tokens/tokens-debug-dp.css +39 -3
  164. package/lib/dist/tokens/tokens-dp-dark.css +81 -45
  165. package/lib/dist/tokens/tokens-dp-light.css +75 -39
  166. package/lib/dist/tokens/tokens-expressive-dark.css +81 -45
  167. package/lib/dist/tokens/tokens-expressive-light.css +75 -39
  168. package/lib/dist/tokens/tokens-expressive-sm-dark.css +81 -45
  169. package/lib/dist/tokens/tokens-expressive-sm-light.css +75 -39
  170. package/lib/dist/tokens/tokens-high-desert-dark.css +81 -45
  171. package/lib/dist/tokens/tokens-high-desert-light.css +75 -39
  172. package/lib/dist/tokens/tokens-melon-dark.css +81 -45
  173. package/lib/dist/tokens/tokens-melon-light.css +75 -39
  174. package/lib/dist/tokens/tokens-plum-dark.css +81 -45
  175. package/lib/dist/tokens/tokens-plum-light.css +75 -39
  176. package/lib/dist/tokens/tokens-prota-deuter-dark.css +79 -43
  177. package/lib/dist/tokens/tokens-prota-deuter-light.css +74 -38
  178. package/lib/dist/tokens/tokens-sunflower-dark.css +81 -45
  179. package/lib/dist/tokens/tokens-sunflower-light.css +75 -39
  180. package/lib/dist/tokens/tokens-tmo-dark.css +81 -45
  181. package/lib/dist/tokens/tokens-tmo-light.css +75 -39
  182. package/lib/dist/tokens/tokens-trita-dark.css +81 -45
  183. package/lib/dist/tokens/tokens-trita-light.css +75 -39
  184. package/lib/dist/tokens/tokens-verdant-haze-dark.css +81 -45
  185. package/lib/dist/tokens/tokens-verdant-haze-light.css +75 -39
  186. package/lib/dist/tokens-docs.json +1 -1
  187. package/package.json +10 -5
@@ -8,8 +8,8 @@ const FOREGROUND_MAP = {
8
8
  'black-900': 'primary',
9
9
  'red-600': 'critical',
10
10
  'red-700': 'critical-strong',
11
- 'green-800': 'success',
12
- 'green-900': 'success-strong',
11
+ 'green-800': 'positive',
12
+ 'green-900': 'positive-strong',
13
13
  'gold-800': 'warning',
14
14
  };
15
15
 
@@ -26,9 +26,9 @@ const SURFACE_MAP = {
26
26
  'gold-50': 'warning-subtle',
27
27
  'gold-100': 'warning',
28
28
  'gold-400': 'warning-strong',
29
- 'green-50': 'success-subtle',
30
- 'green-100': 'success',
31
- 'green-800': 'success-strong',
29
+ 'green-50': 'positive-subtle',
30
+ 'green-100': 'positive',
31
+ 'green-800': 'positive-strong',
32
32
  'blue-50': 'info-subtle',
33
33
  'blue-100': 'info',
34
34
  'blue-800': 'info-strong',
@@ -41,9 +41,9 @@ const BORDER_MAP = {
41
41
  'red-300': 'critical-subtle',
42
42
  'red-600': 'critical',
43
43
  'red-800': 'critical-strong',
44
- 'green-300': 'success-subtle',
45
- 'green-700': 'success',
46
- 'green-900': 'success-strong',
44
+ 'green-300': 'positive-subtle',
45
+ 'green-700': 'positive',
46
+ 'green-900': 'positive-strong',
47
47
  'gold-300': 'warning-subtle',
48
48
  'gold-500': 'warning',
49
49
  'gold-700': 'warning-strong',
@@ -22,6 +22,14 @@ const SPACING_MAP = {
22
22
  // For tokens used in layout context (width, height, etc.)
23
23
  // Exact matches are labeled; nearest-neighbor approximations note the delta.
24
24
  const LAYOUT_MAP = {
25
+ // Off-scale pixel-indexed exceptions (DLT-3330) — exact matches via Npx stops.
26
+ // Old --dt-size-N stop at these pixel values has no scale-indexed layout equivalent;
27
+ // route to the off-scale Npx token in layout-property context.
28
+ 100: '1px', // 1px
29
+ 200: '2px', // 2px
30
+ 400: '8px', // 8px
31
+ 525: '20px', // 20px
32
+ 550: '24px', // 24px
25
33
  // Exact scale matches
26
34
  500: '25', // 16px
27
35
  600: '50', // 32px
@@ -144,6 +152,8 @@ export default {
144
152
  'eg. padding: var(--dt-size-400) → padding: var(--dt-spacing-100)\n' +
145
153
  '- Layout properties (width, height, min/max, flex-basis) → var(--dt-layout-*)\n\t' +
146
154
  'eg. width: var(--dt-size-700) → width: var(--dt-layout-100)\n' +
155
+ '- Off-scale layout exceptions: width: var(--dt-size-400) → width: var(--dt-layout-8px)\n\t' +
156
+ '(covers 100/200/400/525/550 stops → 1px/2px/8px/20px/24px in layout context only)\n' +
147
157
  '- Percentage tokens → var(--dt-layout-*-percent)\n\t' +
148
158
  'eg. var(--dt-size-100-percent) → var(--dt-layout-100-percent)\n' +
149
159
  '- Tokens exceeding the layout scale (>1024px) are converted to raw rem with a TODO comment.\n' +
@@ -0,0 +1,73 @@
1
+ // Migration: deprecated `success` color tokens and utility classes → `positive`.
2
+ //
3
+ // Suffixes are enumerated and anchored so words like "successful" /
4
+ // "successfully" (which start with "success") are NOT matched — matches must
5
+ // be followed by `)`, end-of-class boundary, or one of the known suffix tails.
6
+
7
+ const SUFFIX_ALTERNATION =
8
+ '-subtle-opaque-inverted|' +
9
+ '-subtle-opaque|' +
10
+ '-subtle-inverted|' +
11
+ '-strong-inverted|' +
12
+ '-opaque-inverted|' +
13
+ '-inverted-hover|' +
14
+ '-subtle|' +
15
+ '-strong|' +
16
+ '-opaque|' +
17
+ '-inverted|' +
18
+ '-hover';
19
+
20
+ const SUCCESS_WITH_SUFFIX = `success((?:${SUFFIX_ALTERNATION})?)`;
21
+
22
+ // Left-edge boundary: previous character must not be a class-name character.
23
+ // Prevents `my-d-fc-success` from being rewritten to `my-d-fc-positive`.
24
+ const CLASS_BOUNDARY_START = `(?<![A-Za-z0-9_-])`;
25
+
26
+ // Right-edge boundary for utility-class matches: end-of-string, whitespace,
27
+ // quote, `>`, `<`, `:`, `=`, `,`, `;`, `}`, `)`, `]`, `(`, `[`, `!`, `\``,
28
+ // `.`, `/`. Prevents `d-fc-successfoo` and partial extensions.
29
+ const CLASS_BOUNDARY_END = `(?=$|[\\s"'><:=,;{}()\\[\\]!\`./])`;
30
+
31
+ export default {
32
+ description:
33
+ 'Renames deprecated `success` color references to `positive`.\n' +
34
+ '- CSS variables: var(--dt-color-{foreground|surface|border|link}-success*) →\n\t' +
35
+ 'var(--dt-color-{foreground|surface|border|link}-positive*)\n\t' +
36
+ 'eg. var(--dt-color-foreground-success-strong) → var(--dt-color-foreground-positive-strong)\n' +
37
+ '- Component-specific tokens: var(--dt-badge-color-background-success) →\n\t' +
38
+ 'var(--dt-badge-color-background-positive); var(--dt-inputs-color-border-success) →\n\t' +
39
+ 'var(--dt-inputs-color-border-positive).\n' +
40
+ '- Utility classes: d-{fc|bgc|bc}-success* → d-{fc|bgc|bc}-positive*\n\t' +
41
+ 'eg. d-bgc-success-subtle-opaque → d-bgc-positive-subtle-opaque\n' +
42
+ '- Suffix variants covered: -subtle, -strong, -opaque, -subtle-opaque,\n\t' +
43
+ '-inverted, -subtle-inverted, -strong-inverted, -opaque-inverted,\n\t' +
44
+ '-subtle-opaque-inverted, -hover, -inverted-hover.\n' +
45
+ '- The match is anchored so unrelated identifiers like "successful" or\n\t' +
46
+ '"successfully" are NOT touched.\n',
47
+ patterns: ['**/*.{css,less,scss,sass,styl,html,vue,md,js,ts,jsx,tsx}'],
48
+ globbyConfig: {
49
+ ignore: ['**/dialtone_migration_helper/tests/**'],
50
+ },
51
+ expressions: [
52
+ // CSS variable: var(--dt-color-{role}-success{suffix?})
53
+ {
54
+ from: new RegExp(`var\\(--dt-color-(foreground|surface|border|link)-${SUCCESS_WITH_SUFFIX}\\)`, 'g'),
55
+ to: (_match, role, suffix) => `var(--dt-color-${role}-positive${suffix})`,
56
+ },
57
+ // Component-specific tokens that DLT-3331's initial sweep missed (no suffix variants).
58
+ {
59
+ from: /var\(--dt-badge-color-background-success\)/g,
60
+ to: () => 'var(--dt-badge-color-background-positive)',
61
+ },
62
+ {
63
+ from: /var\(--dt-inputs-color-border-success\)/g,
64
+ to: () => 'var(--dt-inputs-color-border-positive)',
65
+ },
66
+ // Utility class: d-{fc|bgc|bc}-success{suffix?}. d-fc-* covers stragglers
67
+ // from the base-to-semantic foreground rename.
68
+ {
69
+ from: new RegExp(`${CLASS_BOUNDARY_START}d-(fc|bgc|bc)-${SUCCESS_WITH_SUFFIX}${CLASS_BOUNDARY_END}`, 'g'),
70
+ to: (_match, prefix, suffix) => `d-${prefix}-positive${suffix}`,
71
+ },
72
+ ],
73
+ };
@@ -2,8 +2,13 @@
2
2
  // e.g. d-h16 → d-h-25, d-p8 → d-p-100, d-m8 → d-m-100
3
3
 
4
4
  // Sizing: pixel value → layout token stop
5
- // MUST STAY IN SYNC with WIDTH_HEIGHTS_LAYOUT in dialtone-css/postcss/constants.cjs
5
+ // MUST STAY IN SYNC with LAYOUT_STOPS in dialtone-css/postcss/constants.cjs
6
+ // Off-scale pixel-indexed exceptions (1, 2, 8, 20, 24) map to the Npx stops
7
+ // introduced in DLT-3330; scale-indexed values (16+) map to the 64px-base stops.
6
8
  const SIZING_MAP = {
9
+ // Off-scale pixel-indexed exceptions
10
+ 1: '1px', 2: '2px', 8: '8px', 20: '20px', 24: '24px',
11
+ // Scale-indexed stops (64px base)
7
12
  16: '25', 32: '50', 48: '75', 64: '100', 80: '125', 96: '150',
8
13
  112: '175', 128: '200', 160: '250', 192: '300', 224: '350', 256: '400',
9
14
  288: '450', 320: '500', 352: '550', 384: '600', 416: '650', 448: '700',
@@ -13,10 +18,8 @@ const SIZING_MAP = {
13
18
  992: '1550', 1024: '1600',
14
19
  };
15
20
 
16
- // Small sizing values (0-12px) that map to spacing tokens, not layout tokens.
17
- // These old classes (d-h0, d-h1, d-h2, etc.) don't have a layout-stop equivalent.
18
- // They should be migrated to use the spacing token directly in CSS rather than a utility class,
19
- // or left as-is since the old classes still work.
21
+ // Remaining off-scale sizing values without a layout-token equivalent (4, 6, 10, 12, 14)
22
+ // are left on the Tier 1 calc-based legacy path and pass through unchanged.
20
23
 
21
24
  // Spacing: pixel value → spacing token stop
22
25
  // MUST STAY IN SYNC with GAP_SPACES_SPACING / MARGIN_SIZES_SPACING / PADDING_SIZES_SPACING in dialtone-css/postcss/constants.cjs
@@ -38,27 +41,82 @@ const SPACING_LAYOUT_MAP = {
38
41
  96: '150', 128: '200',
39
42
  };
40
43
 
41
- // Helper: build regex that matches class names with word boundaries
42
- // Sorted by descending key length to avoid partial matches (d-h1024 before d-h102)
44
+ // Border-radius: legacy pixel value new radius token stop
45
+ // MUST STAY IN SYNC with RADIUS_STOPS in dialtone-css/postcss/constants.cjs.
46
+ const RADIUS_MAP = {
47
+ 0: '0', 1: '100', 2: '200', 4: '300', 6: '350',
48
+ 8: '400', 12: '450', 16: '500', 24: '550', 32: '600',
49
+ };
50
+
51
+ // Border-radius: legacy physical-side prefix → new logical prefix.
52
+ const RADIUS_PAIR_PREFIX_MAP = {
53
+ btr: 'bbsr', // top → block-start pair
54
+ bbr: 'bber', // bottom → block-end pair
55
+ blr: 'bisr', // left → inline-start pair
56
+ brr: 'bier', // right → inline-end pair
57
+ };
58
+
59
+ // Class-name boundary: preceded by space, quote, or start; followed by space, quote, or end.
60
+ const CLASS_BOUNDARY_LEFT = `((?:^|["'\\s]))`;
61
+ const CLASS_BOUNDARY_RIGHT = `((?:["'\\s]|$))`;
62
+
63
+ // Build regex that matches class names ending in any key from `map`, with boundaries.
64
+ // Keys sorted by descending length to avoid partial matches (d-h1024 before d-h102).
43
65
  function buildClassRegex (prefix, map) {
44
66
  const keys = Object.keys(map).sort((a, b) => b.length - a.length || Number(b) - Number(a));
45
- const pattern = keys.join('|');
46
- // Match class name boundary: preceded by space, quote, or start; followed by space, quote, or end
47
- return new RegExp(`((?:^|["'\\s]))${prefix}(${pattern})((?:["'\\s]|$))`, 'gm');
67
+ return new RegExp(`${CLASS_BOUNDARY_LEFT}${prefix}(${keys.join('|')})${CLASS_BOUNDARY_RIGHT}`, 'gm');
68
+ }
69
+
70
+ // Variant for fixed-keyword suffixes (e.g. `-pill`, `-circle`).
71
+ function buildKeywordClassRegex (prefix, keyword) {
72
+ return new RegExp(`${CLASS_BOUNDARY_LEFT}${prefix}-${keyword}${CLASS_BOUNDARY_RIGHT}`, 'gm');
48
73
  }
49
74
 
50
75
  export default {
51
76
  description:
52
77
  'Migrates pixel-based utility class names to token-stop-based names.\n' +
53
78
  '- Sizing: d-h16 → d-h-25, d-w64 → d-w-100, d-hmn96 → d-hmn-150\n' +
79
+ '- Off-scale sizing: d-w1 → d-w-1px, d-h24 → d-h-24px (pixel-indexed exceptions)\n' +
54
80
  '- Margin: d-m8 → d-m-100, d-mt16 → d-mt-200, d-mtn8 → d-mt-n100\n' +
55
81
  '- Padding: d-p8 → d-p-100, d-pt16 → d-pt-200\n' +
56
82
  '- Gap: d-g8 → d-g-100, d-rg16 → d-rg-200\n' +
57
83
  '- Position: d-t8 → d-t-100, d-tn8 → d-t-n100\n' +
84
+ '- Border-radius all: d-bar6 → d-bar-350, d-bar24 → d-bar-550\n' +
85
+ '- Border-radius pair (physical → logical): d-btr6 → d-bbsr-350, d-bbr8 → d-bber-400, d-blr12 → d-bisr-450, d-brr16 → d-bier-500\n' +
86
+ '- Border-radius pair keyword: d-btr-pill → d-bbsr-pill, d-brr-circle → d-bier-circle\n' +
58
87
  '- Old deprecated sizes (d-h72, d-w332, etc.) are left unchanged for manual review.\n',
59
- patterns: ['**/*.{vue,html,js,ts,jsx,tsx,md,less,css}'],
88
+ patterns: ['**/*.{vue,html,js,ts,jsx,tsx,md,mdx,less,css}'],
60
89
  globbyConfig: {
61
- ignore: ['**/dialtone_migration_helper/tests/**', '**/node_modules/**'],
90
+ // Include dotfiles/dotdirs so tooling directories like `.vuepress/baseComponents/`,
91
+ // `.storybook/`, and per-repo docs folders are scanned. Dotted build-output caches are
92
+ // explicitly excluded below.
93
+ dot: true,
94
+ ignore: [
95
+ '**/node_modules/**',
96
+ // `dot: true` makes dot-dirs globbable; explicitly exclude the git directory.
97
+ '**/.git/**',
98
+ // Built outputs: regenerated on next build; rewriting selectors in co-selected rules
99
+ // (`.d-bar-350, .d-bar6 { ... }`) would corrupt them since the leading whitespace
100
+ // before the legacy selector looks like a class boundary to the regex.
101
+ '**/dist/**',
102
+ '**/build/**',
103
+ '**/lib/dist/**',
104
+ // Framework caches
105
+ '**/.cache/**',
106
+ '**/.vite/**',
107
+ '**/.vuepress/.cache/**',
108
+ '**/.vuepress/.temp/**',
109
+ '**/.vuepress/dist/**',
110
+ '**/.next/**',
111
+ '**/.nuxt/**',
112
+ '**/.turbo/**',
113
+ '**/.nx/**',
114
+ // Migration-helper test fixtures intentionally contain legacy class names.
115
+ '**/dialtone_migration_helper/tests/**',
116
+ // ESLint-plugin rules and tests inherently contain legacy class names as regex patterns
117
+ // and test inputs — they're the tool that detects the legacy classes, don't rewrite them.
118
+ '**/eslint-plugin-dialtone/**',
119
+ ],
62
120
  },
63
121
  expressions: [
64
122
  // ── Sizing: d-h{px} → d-h-{layout-stop} ──────────────────────────────
@@ -131,5 +189,27 @@ export default {
131
189
  from: buildClassRegex(`d-${prefix}n`, NEGATIVE_SPACING_MAP),
132
190
  to: (match, pre, px, post) => `${pre}d-${prefix}-n${NEGATIVE_SPACING_MAP[px]}${post}`,
133
191
  })),
192
+
193
+ // ── Border-radius all-corners numeric: d-bar{px} → d-bar-{stop} ──────
194
+ {
195
+ from: buildClassRegex('d-bar', RADIUS_MAP),
196
+ to: (match, pre, px, post) => `${pre}d-bar-${RADIUS_MAP[px]}${post}`,
197
+ },
198
+
199
+ // ── Border-radius side-pair numeric: d-{legacy}{px} → d-{logical}-{stop}
200
+ // Physical pair prefixes (btr/bbr/blr/brr) rewrite to their logical siblings (bbsr/bber/bisr/bier).
201
+ ...Object.entries(RADIUS_PAIR_PREFIX_MAP).map(([legacy, logical]) => ({
202
+ from: buildClassRegex(`d-${legacy}`, RADIUS_MAP),
203
+ to: (match, pre, px, post) => `${pre}d-${logical}-${RADIUS_MAP[px]}${post}`,
204
+ })),
205
+
206
+ // ── Border-radius side-pair keyword: d-{legacy}-{pill|circle} → d-{logical}-{pill|circle}
207
+ // Legacy `.d-bar-pill` / `.d-bar-circle` stay as-is (same name in the new scheme).
208
+ ...Object.entries(RADIUS_PAIR_PREFIX_MAP).flatMap(([legacy, logical]) =>
209
+ ['pill', 'circle'].map(keyword => ({
210
+ from: buildKeywordClassRegex(`d-${legacy}`, keyword),
211
+ to: (match, pre, post) => `${pre}d-${logical}-${keyword}${post}`,
212
+ })),
213
+ ),
134
214
  ],
135
215
  };
@@ -14,8 +14,8 @@
14
14
  <p class="d-fc-black-900">primary text</p>
15
15
  <p class="d-fc-red-600">critical text</p>
16
16
  <p class="d-fc-red-700">critical-strong text</p>
17
- <p class="d-fc-green-800">success text</p>
18
- <p class="d-fc-green-900">success-strong text</p>
17
+ <p class="d-fc-green-800">positive text</p>
18
+ <p class="d-fc-green-900">positive-strong text</p>
19
19
  <p class="d-fc-gold-800">warning text</p>
20
20
 
21
21
  <!-- Unmapped foreground classes (should NOT be replaced) -->
@@ -41,9 +41,9 @@
41
41
  <div class="d-bgc-gold-50">warning-subtle</div>
42
42
  <div class="d-bgc-gold-100">warning</div>
43
43
  <div class="d-bgc-gold-400">warning-strong</div>
44
- <div class="d-bgc-green-50">success-subtle</div>
45
- <div class="d-bgc-green-100">success</div>
46
- <div class="d-bgc-green-800">success-strong</div>
44
+ <div class="d-bgc-green-50">positive-subtle</div>
45
+ <div class="d-bgc-green-100">positive</div>
46
+ <div class="d-bgc-green-800">positive-strong</div>
47
47
  <div class="d-bgc-blue-50">info-subtle</div>
48
48
  <div class="d-bgc-blue-100">info</div>
49
49
  <div class="d-bgc-blue-800">info-strong</div>
@@ -62,9 +62,9 @@
62
62
  <div class="d-bc-red-300">critical-subtle</div>
63
63
  <div class="d-bc-red-600">critical</div>
64
64
  <div class="d-bc-red-800">critical-strong</div>
65
- <div class="d-bc-green-300">success-subtle</div>
66
- <div class="d-bc-green-700">success</div>
67
- <div class="d-bc-green-900">success-strong</div>
65
+ <div class="d-bc-green-300">positive-subtle</div>
66
+ <div class="d-bc-green-700">positive</div>
67
+ <div class="d-bc-green-900">positive-strong</div>
68
68
  <div class="d-bc-gold-300">warning-subtle</div>
69
69
  <div class="d-bc-gold-500">warning</div>
70
70
  <div class="d-bc-gold-700">warning-strong</div>
@@ -78,14 +78,14 @@
78
78
  <!-- ============================================ -->
79
79
 
80
80
  <div class="d-divide-red-600">critical divide</div>
81
- <div class="d-divide-green-700">success divide</div>
81
+ <div class="d-divide-green-700">positive divide</div>
82
82
 
83
83
  <!-- ============================================ -->
84
84
  <!-- PSEUDO & RESPONSIVE PREFIXED -->
85
85
  <!-- ============================================ -->
86
86
 
87
87
  <p class="h:d-fc-red-600">hover critical text</p>
88
- <p class="f:d-fc-green-800">focus success text</p>
88
+ <p class="f:d-fc-green-800">focus positive text</p>
89
89
  <div class="sm:d-bgc-black-100">responsive secondary surface</div>
90
90
  <div class="md:d-bc-red-600">responsive critical border</div>
91
91
 
@@ -16,20 +16,20 @@ describe('base-to-semantic config', () => {
16
16
  ['FOREGROUND_MAP', 'fc', [
17
17
  ['black-600', 'tertiary'], ['black-700', 'secondary'], ['black-900', 'primary'],
18
18
  ['red-600', 'critical'], ['red-700', 'critical-strong'],
19
- ['green-800', 'success'], ['green-900', 'success-strong'], ['gold-800', 'warning'],
19
+ ['green-800', 'positive'], ['green-900', 'positive-strong'], ['gold-800', 'warning'],
20
20
  ]],
21
21
  ['SURFACE_MAP', 'bgc', [
22
22
  ['black-50', 'primary'], ['black-100', 'secondary'], ['black-200', 'moderate'],
23
23
  ['black-300', 'bold'], ['black-600', 'strong'], ['black-800', 'contrast'],
24
24
  ['red-50', 'critical-subtle'], ['red-100', 'critical'], ['red-600', 'critical-strong'],
25
25
  ['gold-50', 'warning-subtle'], ['gold-100', 'warning'], ['gold-400', 'warning-strong'],
26
- ['green-50', 'success-subtle'], ['green-100', 'success'], ['green-800', 'success-strong'],
26
+ ['green-50', 'positive-subtle'], ['green-100', 'positive'], ['green-800', 'positive-strong'],
27
27
  ['blue-50', 'info-subtle'], ['blue-100', 'info'], ['blue-800', 'info-strong'],
28
28
  ['purple-50', 'brand-subtle'], ['purple-100', 'brand'], ['purple-600', 'brand-strong'],
29
29
  ]],
30
30
  ['BORDER_MAP', 'bc', [
31
31
  ['red-300', 'critical-subtle'], ['red-600', 'critical'], ['red-800', 'critical-strong'],
32
- ['green-300', 'success-subtle'], ['green-700', 'success'], ['green-900', 'success-strong'],
32
+ ['green-300', 'positive-subtle'], ['green-700', 'positive'], ['green-900', 'positive-strong'],
33
33
  ['gold-300', 'warning-subtle'], ['gold-500', 'warning'], ['gold-700', 'warning-strong'],
34
34
  ['purple-300', 'brand-subtle'], ['purple-600', 'brand'], ['purple-800', 'brand-strong'],
35
35
  ['blue-500', 'focus'],
@@ -50,8 +50,8 @@ describe('base-to-semantic config', () => {
50
50
  it('d-divide-red-600 → d-divide-critical', () => {
51
51
  assert.equal(apply('d-divide-red-600'), 'd-divide-critical');
52
52
  });
53
- it('d-divide-green-700 → d-divide-success', () => {
54
- assert.equal(apply('d-divide-green-700'), 'd-divide-success');
53
+ it('d-divide-green-700 → d-divide-positive', () => {
54
+ assert.equal(apply('d-divide-green-700'), 'd-divide-positive');
55
55
  });
56
56
  });
57
57
 
@@ -99,14 +99,14 @@ describe('base-to-semantic config', () => {
99
99
  ['.a { background: var(--dt-color-black-100) url(\'b.png\') no-repeat center; }',
100
100
  'surface-secondary', 'bg: color before image'],
101
101
  ['.a { background: url(\'i.svg\') no-repeat var(--dt-color-green-100); }',
102
- 'surface-success', 'bg: color after image'],
102
+ 'surface-positive', 'bg: color after image'],
103
103
  ['.a { background: var(--dt-color-blue-100) no-repeat center / cover; }',
104
104
  'surface-info', 'bg: color + size shorthand'],
105
105
  ['.a { background: var(--dt-color-red-50) url(\'t.png\') repeat-x top left; }',
106
106
  'surface-critical-subtle', 'bg: color + image + repeat + position'],
107
107
  // border-color → border
108
108
  ['.a { border-color: var(--dt-color-red-600); }', 'border-critical', 'border-color:'],
109
- ['.a { border-top-color: var(--dt-color-green-700); }', 'border-success', 'border-top-color:'],
109
+ ['.a { border-top-color: var(--dt-color-green-700); }', 'border-positive', 'border-top-color:'],
110
110
  // border shorthand
111
111
  ['.a { border: var(--dt-size-border-300) solid var(--dt-color-red-600); }',
112
112
  'border-critical', 'border shorthand'],
@@ -114,7 +114,7 @@ describe('base-to-semantic config', () => {
114
114
  ['.a { border-block-start: var(--dt-size-border-100) solid var(--dt-color-red-600); }',
115
115
  'border-critical', 'border-block-start'],
116
116
  ['.a { border-inline-end-color: var(--dt-color-green-700); }',
117
- 'border-success', 'border-inline-end-color'],
117
+ 'border-positive', 'border-inline-end-color'],
118
118
  ['.a { border-block-end-color: var(--dt-color-gold-500); }',
119
119
  'border-warning', 'border-block-end-color'],
120
120
  ];
@@ -27,6 +27,13 @@
27
27
  <div :style="{ height: 'var(--dt-size-800)' }">size-800 on height → layout-200</div>
28
28
  <div :style="{ maxWidth: 'var(--dt-size-1000)' }">size-1000 on max-width → layout-800</div>
29
29
 
30
+ <!-- Off-scale pixel-indexed exceptions (DLT-3330) — layout context only -->
31
+ <div :style="{ width: 'var(--dt-size-100)' }">size-100 on width → layout-1px</div>
32
+ <div :style="{ height: 'var(--dt-size-200)' }">size-200 on height → layout-2px</div>
33
+ <div :style="{ minInlineSize: 'var(--dt-size-400)' }">size-400 on min-inline-size → layout-8px</div>
34
+ <div :style="{ maxWidth: 'var(--dt-size-525)' }">size-525 on max-width → layout-20px</div>
35
+ <div :style="{ blockSize: 'var(--dt-size-550)' }">size-550 on block-size → layout-24px</div>
36
+
30
37
  <!-- Skip: already-migrated tokens -->
31
38
  <div :style="{ width: 'var(--dt-layout-100)' }">already layout-100</div>
32
39
  <p :style="{ padding: 'var(--dt-spacing-100)' }">already spacing-100</p>
@@ -113,6 +120,15 @@
113
120
  inline-size: var(--dt-size-1100); /* → layout-1600 (1024px) */
114
121
  }
115
122
 
123
+ /* off-scale pixel-indexed exceptions (DLT-3330) — only route in layout context */
124
+ .test-width-off-scale {
125
+ inline-size: var(--dt-size-100); /* → layout-1px (1px) */
126
+ block-size: var(--dt-size-200); /* → layout-2px (2px) */
127
+ min-inline-size: var(--dt-size-400); /* → layout-8px (8px) */
128
+ max-inline-size: var(--dt-size-525); /* → layout-20px (20px) */
129
+ max-block-size: var(--dt-size-550); /* → layout-24px (24px) */
130
+ }
131
+
116
132
  /* height */
117
133
  .test-height {
118
134
  block-size: var(--dt-size-700);
@@ -0,0 +1,87 @@
1
+ import { describe, it } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import config from '../configs/size-to-layout.mjs';
4
+ import { applyConfig } from './helpers.mjs';
5
+
6
+ const apply = (input) => applyConfig(config, input);
7
+
8
+ describe('size-to-layout config', () => {
9
+ // ─── Off-scale pixel-indexed exceptions (DLT-3330) ────────────────────
10
+ //
11
+ // Layout-property context only: old --dt-size-N stop at these pixel values
12
+ // maps to the off-scale --dt-layout-Npx token.
13
+ // 100 → 1px, 200 → 2px, 400 → 8px, 525 → 20px, 550 → 24px
14
+
15
+ describe('off-scale exceptions — layout context routes to --dt-layout-Npx', () => {
16
+ const offScaleCases = [
17
+ ['width', '--dt-size-100', '--dt-layout-1px'],
18
+ ['height', '--dt-size-200', '--dt-layout-2px'],
19
+ ['min-inline-size', '--dt-size-400', '--dt-layout-8px'],
20
+ ['max-width', '--dt-size-525', '--dt-layout-20px'],
21
+ ['block-size', '--dt-size-550', '--dt-layout-24px'],
22
+ ['inline-size', '--dt-size-100', '--dt-layout-1px'],
23
+ ['min-height', '--dt-size-400', '--dt-layout-8px'],
24
+ ['flex-basis', '--dt-size-400', '--dt-layout-8px'],
25
+ ];
26
+
27
+ for (const [prop, from, to] of offScaleCases) {
28
+ it(`${prop}: var(${from}) → var(${to})`, () => {
29
+ const result = apply(`.x { ${prop}: var(${from}); }`);
30
+ assert.equal(result, `.x { ${prop}: var(${to}); }`);
31
+ });
32
+ }
33
+ });
34
+
35
+ describe('off-scale exceptions — spacing context STILL routes to --dt-spacing-* (regression guard)', () => {
36
+ // These are the same stops, but used in spacing-property context.
37
+ // The LAYOUT_MAP additions must NOT leak into spacing routing.
38
+ const spacingRegressionCases = [
39
+ ['padding', '--dt-size-100', '--dt-spacing-1'],
40
+ ['margin', '--dt-size-200', '--dt-spacing-25'],
41
+ ['gap', '--dt-size-400', '--dt-spacing-100'],
42
+ ['padding-block', '--dt-size-525', '--dt-spacing-250'],
43
+ ['margin-inline', '--dt-size-550', '--dt-spacing-300'],
44
+ ['inset', '--dt-size-400', '--dt-spacing-100'],
45
+ ];
46
+
47
+ for (const [prop, from, to] of spacingRegressionCases) {
48
+ it(`${prop}: var(${from}) → var(${to})`, () => {
49
+ const result = apply(`.x { ${prop}: var(${from}); }`);
50
+ assert.equal(result, `.x { ${prop}: var(${to}); }`);
51
+ });
52
+ }
53
+ });
54
+
55
+ // ─── Existing scale-indexed behavior unchanged (smoke tests) ──────────
56
+
57
+ describe('scale-indexed stops — unchanged', () => {
58
+ const scaleCases = [
59
+ ['width', '--dt-size-500', '--dt-layout-25'], // 16px
60
+ ['width', '--dt-size-700', '--dt-layout-100'], // 64px
61
+ ['width', '--dt-size-1100', '--dt-layout-1600'], // 1024px
62
+ ['padding', '--dt-size-700', '--dt-spacing-800'], // 64px
63
+ ['margin', '--dt-size-500', '--dt-spacing-200'], // 16px
64
+ ];
65
+
66
+ for (const [prop, from, to] of scaleCases) {
67
+ it(`${prop}: var(${from}) → var(${to})`, () => {
68
+ const result = apply(`.x { ${prop}: var(${from}); }`);
69
+ assert.equal(result, `.x { ${prop}: var(${to}); }`);
70
+ });
71
+ }
72
+ });
73
+
74
+ // ─── Logical properties and custom property name heuristics ───────────
75
+
76
+ describe('off-scale — custom property name heuristics', () => {
77
+ it('--panel-width: var(--dt-size-400) → --dt-layout-8px', () => {
78
+ const result = apply(`.x { --panel-width: var(--dt-size-400); }`);
79
+ assert.equal(result, `.x { --panel-width: var(--dt-layout-8px); }`);
80
+ });
81
+
82
+ it('--badge-padding-x: var(--dt-size-400) → --dt-spacing-100 (stays spacing)', () => {
83
+ const result = apply(`.x { --badge-padding-x: var(--dt-size-400); }`);
84
+ assert.equal(result, `.x { --badge-padding-x: var(--dt-spacing-100); }`);
85
+ });
86
+ });
87
+ });