@dialpad/dialtone-css 8.78.0-next.1 → 8.78.0-next.3
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 +0 -2
- package/lib/build/js/dialtone_migrate_flex_to_stack/examples-edge-cases.vue +26 -0
- package/lib/build/js/dialtone_migrate_flex_to_stack/index.mjs +56 -15
- package/lib/build/js/dialtone_migrate_tshirt_to_numeric/index.mjs +233 -0
- package/lib/build/js/dialtone_migrate_tshirt_to_numeric/test.mjs +336 -0
- package/lib/build/js/dialtone_migration_helper/configs/physical-to-logical.mjs +86 -0
- package/lib/build/js/dialtone_migration_helper/configs/size-to-layout.mjs +212 -0
- package/lib/build/js/dialtone_migration_helper/configs/space-to-spacing.mjs +48 -0
- package/lib/build/js/dialtone_migration_helper/configs/stack-gap-to-spacing.mjs +88 -0
- package/lib/build/js/dialtone_migration_helper/configs/utility-class-to-token-stops.mjs +135 -0
- package/lib/build/js/dialtone_migration_helper/tests/size-to-layout-test-examples.vue +275 -0
- package/lib/build/js/dialtone_migration_helper/tests/space-to-spacing-test-examples.vue +193 -0
- package/lib/build/less/components/avatar.less +8 -19
- package/lib/build/less/components/badge.less +22 -20
- package/lib/build/less/components/banner.less +5 -5
- package/lib/build/less/components/breadcrumbs.less +4 -4
- package/lib/build/less/components/button.less +39 -39
- package/lib/build/less/components/card.less +4 -4
- package/lib/build/less/components/chip.less +41 -51
- package/lib/build/less/components/codeblock.less +2 -2
- package/lib/build/less/components/collapsible.less +2 -2
- package/lib/build/less/components/combobox-multi-select.less +8 -8
- package/lib/build/less/components/combobox-with-popover.less +1 -1
- package/lib/build/less/components/combobox.less +5 -5
- package/lib/build/less/components/datepicker.less +6 -6
- package/lib/build/less/components/description-list.less +14 -3
- package/lib/build/less/components/dropdown.less +4 -4
- package/lib/build/less/components/emoji-picker.less +35 -35
- package/lib/build/less/components/empty-state.less +5 -5
- package/lib/build/less/components/filter-pill.less +5 -5
- package/lib/build/less/components/forms.less +10 -10
- package/lib/build/less/components/image-viewer.less +2 -2
- package/lib/build/less/components/input.less +17 -22
- package/lib/build/less/components/item-layout.less +8 -8
- package/lib/build/less/components/keyboard-shortcut.less +3 -3
- package/lib/build/less/components/link.less +5 -5
- package/lib/build/less/components/list-group.less +1 -1
- package/lib/build/less/components/list-item-group.less +1 -1
- package/lib/build/less/components/list-item.less +9 -9
- package/lib/build/less/components/modal.less +20 -20
- package/lib/build/less/components/notice.less +11 -11
- package/lib/build/less/components/pagination.less +5 -5
- package/lib/build/less/components/popover.less +5 -5
- package/lib/build/less/components/radio-checkbox.less +11 -10
- package/lib/build/less/components/rich-text-editor.less +13 -13
- package/lib/build/less/components/scrollbar.less +2 -2
- package/lib/build/less/components/segmented-control.less +6 -6
- package/lib/build/less/components/selects.less +18 -13
- package/lib/build/less/components/skeleton.less +4 -4
- package/lib/build/less/components/stack.less +24 -69
- package/lib/build/less/components/table.less +6 -7
- package/lib/build/less/components/tabs.less +24 -24
- package/lib/build/less/components/toast.less +16 -16
- package/lib/build/less/components/toggle.less +23 -23
- package/lib/build/less/components/tooltip.less +27 -27
- package/lib/build/less/dialtone-reset.less +3 -3
- package/lib/build/less/dialtone-transitions.less +4 -4
- package/lib/build/less/dialtone.less +2 -2
- package/lib/build/less/recipes/attachment_carousel.less +13 -13
- package/lib/build/less/recipes/callbar_button.less +1 -1
- package/lib/build/less/recipes/callbar_button_with_dropdown.less +7 -7
- package/lib/build/less/recipes/callbar_button_with_popover.less +8 -8
- package/lib/build/less/recipes/callbox.less +6 -6
- package/lib/build/less/recipes/contact_info.less +9 -9
- package/lib/build/less/recipes/editor.less +12 -12
- package/lib/build/less/recipes/emoji_row.less +8 -8
- package/lib/build/less/recipes/feed_item_pill.less +13 -13
- package/lib/build/less/recipes/feed_item_row.less +10 -10
- package/lib/build/less/recipes/grouped_chip.less +2 -2
- package/lib/build/less/recipes/ivr_node.less +13 -13
- package/lib/build/less/recipes/leftbar_row.less +23 -23
- package/lib/build/less/recipes/message_input.less +16 -16
- package/lib/build/less/recipes/settings_menu_button.less +10 -10
- package/lib/build/less/recipes/time_pill.less +1 -1
- package/lib/build/less/recipes/top_banner_info.less +8 -8
- package/lib/build/less/recipes/unread_pill.less +2 -2
- package/lib/build/less/themes/default.less +1 -1
- package/lib/build/less/utilities/backgrounds.less +3 -3
- package/lib/build/less/utilities/effects.less +20 -20
- package/lib/build/less/utilities/flex.less +11 -11
- package/lib/build/less/utilities/layout.less +4 -4
- package/lib/build/less/utilities/sizing.less +172 -0
- package/lib/build/less/utilities/spacing.less +49 -49
- package/lib/build/less/utilities/typography.less +2 -2
- package/lib/build/less/variables/sizes.less +8 -8
- package/lib/dist/dialtone-default-theme.css +5220 -1117
- package/lib/dist/dialtone-default-theme.min.css +1 -1
- package/lib/dist/dialtone-docs.json +1 -1
- package/lib/dist/dialtone.css +5203 -1117
- package/lib/dist/dialtone.min.css +1 -1
- package/lib/dist/js/dialtone_migrate_flex_to_stack/examples-edge-cases.vue +26 -0
- package/lib/dist/js/dialtone_migrate_flex_to_stack/index.mjs +56 -15
- package/lib/dist/js/dialtone_migrate_tshirt_to_numeric/index.mjs +233 -0
- package/lib/dist/js/dialtone_migrate_tshirt_to_numeric/test.mjs +336 -0
- package/lib/dist/js/dialtone_migration_helper/configs/physical-to-logical.mjs +86 -0
- package/lib/dist/js/dialtone_migration_helper/configs/size-to-layout.mjs +212 -0
- package/lib/dist/js/dialtone_migration_helper/configs/space-to-spacing.mjs +48 -0
- package/lib/dist/js/dialtone_migration_helper/configs/stack-gap-to-spacing.mjs +88 -0
- package/lib/dist/js/dialtone_migration_helper/configs/utility-class-to-token-stops.mjs +135 -0
- package/lib/dist/js/dialtone_migration_helper/tests/size-to-layout-test-examples.vue +275 -0
- package/lib/dist/js/dialtone_migration_helper/tests/space-to-spacing-test-examples.vue +193 -0
- package/lib/dist/tokens/tokens-base-dark.css +17 -0
- package/lib/dist/tokens/tokens-base-light.css +17 -0
- package/lib/dist/tokens/tokens-debug-base.css +17 -0
- package/lib/dist/tokens-docs.json +1 -1
- package/package.json +3 -3
- package/lib/build/js/dialtone_migration_helper/configs/space-to-size.mjs +0 -15
- package/lib/dist/js/dialtone_migration_helper/configs/space-to-size.mjs +0 -15
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @fileoverview Tests for dialtone-migrate-tshirt-to-numeric codemod.
|
|
5
|
+
* Run: node packages/dialtone-css/lib/build/js/dialtone_migrate_tshirt_to_numeric/test.mjs
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import assert from 'node:assert/strict';
|
|
9
|
+
import { describe, it } from 'node:test';
|
|
10
|
+
import { transformContent } from './index.mjs';
|
|
11
|
+
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
// Tests
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
|
|
16
|
+
describe('Basic size prop transforms', () => {
|
|
17
|
+
it('transforms size="xs" to :size="100"', () => {
|
|
18
|
+
const input = '<dt-button size="xs">Click</dt-button>';
|
|
19
|
+
const expected = '<dt-button :size="100">Click</dt-button>';
|
|
20
|
+
const { transformed, count } = transformContent(input);
|
|
21
|
+
assert.equal(transformed, expected);
|
|
22
|
+
assert.equal(count, 1);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('transforms size="sm" to :size="200"', () => {
|
|
26
|
+
const input = '<dt-text size="sm">Hello</dt-text>';
|
|
27
|
+
const expected = '<dt-text :size="200">Hello</dt-text>';
|
|
28
|
+
const { transformed } = transformContent(input);
|
|
29
|
+
assert.equal(transformed, expected);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('transforms size="md" to :size="300"', () => {
|
|
33
|
+
const input = '<dt-input size="md" label="Name" />';
|
|
34
|
+
const expected = '<dt-input :size="300" label="Name" />';
|
|
35
|
+
const { transformed } = transformContent(input);
|
|
36
|
+
assert.equal(transformed, expected);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('transforms size="lg" to :size="400"', () => {
|
|
40
|
+
const input = '<dt-toggle size="lg" />';
|
|
41
|
+
const expected = '<dt-toggle :size="400" />';
|
|
42
|
+
const { transformed } = transformContent(input);
|
|
43
|
+
assert.equal(transformed, expected);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('transforms size="xl" to :size="500"', () => {
|
|
47
|
+
const input = '<dt-segmented-control size="xl" />';
|
|
48
|
+
const expected = '<dt-segmented-control :size="500" />';
|
|
49
|
+
const { transformed } = transformContent(input);
|
|
50
|
+
assert.equal(transformed, expected);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('transforms size="2xl" to :size="600"', () => {
|
|
54
|
+
const input = '<dt-text kind="headline" size="2xl">Title</dt-text>';
|
|
55
|
+
const expected = '<dt-text kind="headline" :size="600">Title</dt-text>';
|
|
56
|
+
const { transformed } = transformContent(input);
|
|
57
|
+
assert.equal(transformed, expected);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('transforms size="3xl" to :size="700"', () => {
|
|
61
|
+
const input = '<dt-text kind="headline" size="3xl">Title</dt-text>';
|
|
62
|
+
const expected = '<dt-text kind="headline" :size="700">Title</dt-text>';
|
|
63
|
+
const { transformed } = transformContent(input);
|
|
64
|
+
assert.equal(transformed, expected);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
describe('label-size prop transforms', () => {
|
|
69
|
+
it('transforms label-size="xs" to :label-size="100"', () => {
|
|
70
|
+
const input = '<dt-input label-size="xs" label="Name" />';
|
|
71
|
+
const expected = '<dt-input :label-size="100" label="Name" />';
|
|
72
|
+
const { transformed } = transformContent(input);
|
|
73
|
+
assert.equal(transformed, expected);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('transforms label-size="lg" to :label-size="400"', () => {
|
|
77
|
+
const input = '<dt-select-menu label-size="lg" />';
|
|
78
|
+
const expected = '<dt-select-menu :label-size="400" />';
|
|
79
|
+
const { transformed } = transformContent(input);
|
|
80
|
+
assert.equal(transformed, expected);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
describe('speed prop transforms', () => {
|
|
85
|
+
it('transforms speed="sm" to :speed="200"', () => {
|
|
86
|
+
const input = '<dt-motion-text speed="sm" text="Hello" />';
|
|
87
|
+
const expected = '<dt-motion-text :speed="200" text="Hello" />';
|
|
88
|
+
const { transformed } = transformContent(input);
|
|
89
|
+
assert.equal(transformed, expected);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('transforms speed="lg" to :speed="400"', () => {
|
|
93
|
+
const input = '<dt-motion-text speed="lg" text="Hello" />';
|
|
94
|
+
const expected = '<dt-motion-text :speed="400" text="Hello" />';
|
|
95
|
+
const { transformed } = transformContent(input);
|
|
96
|
+
assert.equal(transformed, expected);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
describe('Does NOT transform non-Dialtone components', () => {
|
|
101
|
+
it('ignores size on native elements', () => {
|
|
102
|
+
const input = '<div size="sm">Not a component</div>';
|
|
103
|
+
const { transformed, count } = transformContent(input);
|
|
104
|
+
assert.equal(transformed, input);
|
|
105
|
+
assert.equal(count, 0);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('ignores size on non-dt components', () => {
|
|
109
|
+
const input = '<my-button size="sm">Click</my-button>';
|
|
110
|
+
const { transformed, count } = transformContent(input);
|
|
111
|
+
assert.equal(transformed, input);
|
|
112
|
+
assert.equal(count, 0);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('ignores size on custom elements without dt- prefix', () => {
|
|
116
|
+
const input = '<app-select size="md" />';
|
|
117
|
+
const { transformed, count } = transformContent(input);
|
|
118
|
+
assert.equal(transformed, input);
|
|
119
|
+
assert.equal(count, 0);
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
describe('Does NOT transform already-numeric or dynamic values', () => {
|
|
124
|
+
it('ignores :size="200" (already numeric binding)', () => {
|
|
125
|
+
const input = '<dt-button :size="200">Click</dt-button>';
|
|
126
|
+
const { transformed, count } = transformContent(input);
|
|
127
|
+
assert.equal(transformed, input);
|
|
128
|
+
assert.equal(count, 0);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('ignores :size="sm" (already a v-bind, consumer chose string)', () => {
|
|
132
|
+
const input = '<dt-button :size="sm">Click</dt-button>';
|
|
133
|
+
const { transformed, count } = transformContent(input);
|
|
134
|
+
assert.equal(transformed, input);
|
|
135
|
+
assert.equal(count, 0);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('ignores :label-size="xs" (already a v-bind)', () => {
|
|
139
|
+
const input = '<dt-input :label-size="xs" />';
|
|
140
|
+
const { transformed, count } = transformContent(input);
|
|
141
|
+
assert.equal(transformed, input);
|
|
142
|
+
assert.equal(count, 0);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it('ignores :size="computedSize" (dynamic binding)', () => {
|
|
146
|
+
const input = '<dt-button :size="computedSize">Click</dt-button>';
|
|
147
|
+
const { transformed, count } = transformContent(input);
|
|
148
|
+
assert.equal(transformed, input);
|
|
149
|
+
assert.equal(count, 0);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it('ignores :size="iconSize" (icon size binding)', () => {
|
|
153
|
+
const input = '<dt-icon :size="iconSize" />';
|
|
154
|
+
const { transformed, count } = transformContent(input);
|
|
155
|
+
assert.equal(transformed, input);
|
|
156
|
+
assert.equal(count, 0);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('ignores numeric string size="200" on dt-icon (icon scale)', () => {
|
|
160
|
+
const input = '<dt-icon size="200" name="phone" />';
|
|
161
|
+
const { transformed, count } = transformContent(input);
|
|
162
|
+
assert.equal(transformed, input);
|
|
163
|
+
assert.equal(count, 0);
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
describe('PascalCase component names', () => {
|
|
168
|
+
it('transforms DtButton size', () => {
|
|
169
|
+
const input = '<DtButton size="sm">Click</DtButton>';
|
|
170
|
+
const expected = '<DtButton :size="200">Click</DtButton>';
|
|
171
|
+
const { transformed } = transformContent(input);
|
|
172
|
+
assert.equal(transformed, expected);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
it('transforms DtText size', () => {
|
|
176
|
+
const input = '<DtText size="xl">Title</DtText>';
|
|
177
|
+
const expected = '<DtText :size="500">Title</DtText>';
|
|
178
|
+
const { transformed } = transformContent(input);
|
|
179
|
+
assert.equal(transformed, expected);
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
describe('Multiple transforms in one tag', () => {
|
|
184
|
+
it('transforms size and label-size on same component', () => {
|
|
185
|
+
const input = '<dt-input size="lg" label-size="sm" label="Name" />';
|
|
186
|
+
const expected = '<dt-input :size="400" :label-size="200" label="Name" />';
|
|
187
|
+
const { transformed, count } = transformContent(input);
|
|
188
|
+
assert.equal(transformed, expected);
|
|
189
|
+
assert.equal(count, 2);
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
describe('Multiple components in one template', () => {
|
|
194
|
+
it('transforms all Dialtone components, ignores others', () => {
|
|
195
|
+
const input = `<template>
|
|
196
|
+
<div>
|
|
197
|
+
<dt-button size="sm">Small</dt-button>
|
|
198
|
+
<my-button size="sm">Not Dialtone</my-button>
|
|
199
|
+
<dt-text size="xl">Title</dt-text>
|
|
200
|
+
<dt-icon size="200" name="phone" />
|
|
201
|
+
</div>
|
|
202
|
+
</template>`;
|
|
203
|
+
const expected = `<template>
|
|
204
|
+
<div>
|
|
205
|
+
<dt-button :size="200">Small</dt-button>
|
|
206
|
+
<my-button size="sm">Not Dialtone</my-button>
|
|
207
|
+
<dt-text :size="500">Title</dt-text>
|
|
208
|
+
<dt-icon size="200" name="phone" />
|
|
209
|
+
</div>
|
|
210
|
+
</template>`;
|
|
211
|
+
const { transformed, count } = transformContent(input);
|
|
212
|
+
assert.equal(transformed, expected);
|
|
213
|
+
assert.equal(count, 2);
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
describe('Real-world patterns from the monorepo', () => {
|
|
218
|
+
it('transforms button in notice action slot', () => {
|
|
219
|
+
const input = '<dt-button size="sm" importance="outlined" kind="muted">Action</dt-button>';
|
|
220
|
+
const expected = '<dt-button :size="200" importance="outlined" kind="muted">Action</dt-button>';
|
|
221
|
+
const { transformed } = transformContent(input);
|
|
222
|
+
assert.equal(transformed, expected);
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
it('transforms text inside card variant template', () => {
|
|
226
|
+
const input = '<dt-text as="p" kind="headline" size="md">Lorem ipsum</dt-text>';
|
|
227
|
+
const expected = '<dt-text as="p" kind="headline" :size="300">Lorem ipsum</dt-text>';
|
|
228
|
+
const { transformed } = transformContent(input);
|
|
229
|
+
assert.equal(transformed, expected);
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it('transforms avatar size', () => {
|
|
233
|
+
const input = '<dt-avatar size="md" :full-name="item.id" />';
|
|
234
|
+
const expected = '<dt-avatar :size="300" :full-name="item.id" />';
|
|
235
|
+
const { transformed } = transformContent(input);
|
|
236
|
+
assert.equal(transformed, expected);
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
it('transforms motion-text speed in story', () => {
|
|
240
|
+
const input = '<dt-motion-text speed="md" text="Animated" :auto-start="false" />';
|
|
241
|
+
const expected = '<dt-motion-text :speed="300" text="Animated" :auto-start="false" />';
|
|
242
|
+
const { transformed } = transformContent(input);
|
|
243
|
+
assert.equal(transformed, expected);
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
it('handles multiline component tags', () => {
|
|
247
|
+
const input = `<dt-button
|
|
248
|
+
size="xs"
|
|
249
|
+
kind="muted"
|
|
250
|
+
importance="clear"
|
|
251
|
+
>`;
|
|
252
|
+
const expected = `<dt-button
|
|
253
|
+
:size="100"
|
|
254
|
+
kind="muted"
|
|
255
|
+
importance="clear"
|
|
256
|
+
>`;
|
|
257
|
+
const { transformed } = transformContent(input);
|
|
258
|
+
assert.equal(transformed, expected);
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
describe('Future-proof: any compound *-size prop', () => {
|
|
263
|
+
it('transforms description-size="sm" to :description-size="200"', () => {
|
|
264
|
+
const input = '<dt-input description-size="sm" />';
|
|
265
|
+
const expected = '<dt-input :description-size="200" />';
|
|
266
|
+
const { transformed } = transformContent(input);
|
|
267
|
+
assert.equal(transformed, expected);
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
it('transforms icon-size="lg" to :icon-size="400"', () => {
|
|
271
|
+
const input = '<dt-badge icon-size="lg" />';
|
|
272
|
+
const expected = '<dt-badge :icon-size="400" />';
|
|
273
|
+
const { transformed } = transformContent(input);
|
|
274
|
+
assert.equal(transformed, expected);
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
it('transforms header-size="xl" to :header-size="500"', () => {
|
|
278
|
+
const input = '<dt-card header-size="xl" />';
|
|
279
|
+
const expected = '<dt-card :header-size="500" />';
|
|
280
|
+
const { transformed } = transformContent(input);
|
|
281
|
+
assert.equal(transformed, expected);
|
|
282
|
+
});
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
describe('camelCase prop names', () => {
|
|
286
|
+
it('transforms labelSize="xs" to :labelSize="100"', () => {
|
|
287
|
+
const input = '<dt-input labelSize="xs" />';
|
|
288
|
+
const expected = '<dt-input :labelSize="100" />';
|
|
289
|
+
const { transformed } = transformContent(input);
|
|
290
|
+
assert.equal(transformed, expected);
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
it('transforms descriptionSize="md" to :descriptionSize="300"', () => {
|
|
294
|
+
const input = '<dt-input descriptionSize="md" />';
|
|
295
|
+
const expected = '<dt-input :descriptionSize="300" />';
|
|
296
|
+
const { transformed } = transformContent(input);
|
|
297
|
+
assert.equal(transformed, expected);
|
|
298
|
+
});
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
describe('Excluded props (not component scale sizes)', () => {
|
|
302
|
+
it('ignores button-width-size="md"', () => {
|
|
303
|
+
const input = '<dt-recipe-callbar-button button-width-size="md" />';
|
|
304
|
+
const { transformed, count } = transformContent(input);
|
|
305
|
+
assert.equal(transformed, input);
|
|
306
|
+
assert.equal(count, 0);
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
it('ignores buttonWidthSize="lg"', () => {
|
|
310
|
+
const input = '<DtCallbarButton buttonWidthSize="lg" />';
|
|
311
|
+
const { transformed, count } = transformContent(input);
|
|
312
|
+
assert.equal(transformed, input);
|
|
313
|
+
assert.equal(count, 0);
|
|
314
|
+
});
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
describe('Edge cases', () => {
|
|
318
|
+
it('does not transform size inside text content', () => {
|
|
319
|
+
const input = '<dt-text>The size="sm" option is deprecated</dt-text>';
|
|
320
|
+
const { transformed, count } = transformContent(input);
|
|
321
|
+
assert.equal(transformed, input);
|
|
322
|
+
assert.equal(count, 0);
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
it('returns count of 0 for content with no matches', () => {
|
|
326
|
+
const input = '<div><span>No Dialtone here</span></div>';
|
|
327
|
+
const { count } = transformContent(input);
|
|
328
|
+
assert.equal(count, 0);
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
it('handles empty string', () => {
|
|
332
|
+
const { transformed, count } = transformContent('');
|
|
333
|
+
assert.equal(transformed, '');
|
|
334
|
+
assert.equal(count, 0);
|
|
335
|
+
});
|
|
336
|
+
});
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// Migration: deprecated physical direction slot/prop/event names → logical equivalents.
|
|
2
|
+
// Covers Vue template directives only. Does NOT cover:
|
|
3
|
+
// - #icon on dt-button (ambiguous — requires manual migration)
|
|
4
|
+
// - Dynamic bindings or script-section references
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
description:
|
|
8
|
+
'Renames deprecated physical direction names (left/right/top/bottom/alpha/omega) to\n' +
|
|
9
|
+
'logical equivalents (start/end/blockStart/blockEnd) in Vue template slots, props,\n' +
|
|
10
|
+
'prop values, and events. Does NOT rename #icon on dt-button (ambiguous).',
|
|
11
|
+
patterns: ['**/*.{vue,html,md,js,ts,jsx,tsx}'],
|
|
12
|
+
expressions: [
|
|
13
|
+
// ── Slot renames ──────────────────────────────────────────────────────
|
|
14
|
+
// Longer patterns first to prevent partial matches.
|
|
15
|
+
// e.g. #leftIcon before #left, #rightIcon before #right
|
|
16
|
+
|
|
17
|
+
// #leftIcon → #startIcon
|
|
18
|
+
{ from: /#leftIcon/g, to: '#startIcon' },
|
|
19
|
+
// #rightIcon → #endIcon
|
|
20
|
+
{ from: /#rightIcon/g, to: '#endIcon' },
|
|
21
|
+
// #alphaIcon → #startIcon
|
|
22
|
+
{ from: /#alphaIcon/g, to: '#startIcon' },
|
|
23
|
+
// #omegaIcon → #endIcon
|
|
24
|
+
{ from: /#omegaIcon/g, to: '#endIcon' },
|
|
25
|
+
// #leftContent → #startContent
|
|
26
|
+
{ from: /#leftContent/g, to: '#startContent' },
|
|
27
|
+
// #rightContent → #endContent
|
|
28
|
+
{ from: /#rightContent/g, to: '#endContent' },
|
|
29
|
+
// #omega → #end (word boundary to avoid matching #omegaIcon)
|
|
30
|
+
// Scoped: only dt-split-button uses #omega
|
|
31
|
+
{ from: /#omega(?=[\s"'>])/g, to: '#end' },
|
|
32
|
+
|
|
33
|
+
// Generic short slot names (#left, #right, #bottom) are scoped to known
|
|
34
|
+
// Dialtone components to avoid renaming slots on non-Dialtone components.
|
|
35
|
+
// Uses multiline matching to find the slot within a dt-* or dt-recipe-* tag.
|
|
36
|
+
// Components: dt-item-layout, dt-recipe-callbox, dt-recipe-contact-centers-row,
|
|
37
|
+
// dt-recipe-general-row, dt-recipe-top-banner-info
|
|
38
|
+
|
|
39
|
+
// #left → #start (only on dt-item-layout, dt-recipe-general-row, dt-recipe-top-banner-info)
|
|
40
|
+
{ from: /(<dt-(?:item-layout|recipe-general-row|recipe-top-banner-info)[\s\S]*?)#left(?=[\s"'>])/gm, to: '$1#start' },
|
|
41
|
+
// #right → #end (only on dt-item-layout, dt-recipe-callbox, dt-recipe-contact-centers-row, dt-recipe-top-banner-info)
|
|
42
|
+
{ from: /(<dt-(?:item-layout|recipe-callbox|recipe-contact-centers-row|recipe-top-banner-info)[\s\S]*?)#right(?=[\s"'>])/gm, to: '$1#end' },
|
|
43
|
+
// #bottom → #blockEnd (only on dt-item-layout, dt-recipe-callbox)
|
|
44
|
+
{ from: /(<dt-(?:item-layout|recipe-callbox)[\s\S]*?)#bottom(?=[\s"'>])/gm, to: '$1#blockEnd' },
|
|
45
|
+
|
|
46
|
+
// ── Prop renames ──────────────────────────────────────────────────────
|
|
47
|
+
// Longer patterns first within each prefix group.
|
|
48
|
+
|
|
49
|
+
// alpha-* → start-* (longest first)
|
|
50
|
+
{ from: /alpha-trailing-class/g, to: 'start-trailing-class' },
|
|
51
|
+
{ from: /alpha-tooltip-text/g, to: 'start-tooltip-text' },
|
|
52
|
+
{ from: /alpha-leading-class/g, to: 'start-leading-class' },
|
|
53
|
+
{ from: /alpha-icon-position/g, to: 'start-icon-position' },
|
|
54
|
+
{ from: /alpha-aria-label/g, to: 'start-aria-label' },
|
|
55
|
+
{ from: /alpha-label-class/g, to: 'start-label-class' },
|
|
56
|
+
{ from: /alpha-disabled/g, to: 'start-disabled' },
|
|
57
|
+
{ from: /alpha-loading/g, to: 'start-loading' },
|
|
58
|
+
{ from: /alpha-active/g, to: 'start-active' },
|
|
59
|
+
|
|
60
|
+
// omega-* → end-* (longest first)
|
|
61
|
+
{ from: /omega-tooltip-text/g, to: 'end-tooltip-text' },
|
|
62
|
+
{ from: /omega-aria-label/g, to: 'end-aria-label' },
|
|
63
|
+
{ from: /omega-disabled/g, to: 'end-disabled' },
|
|
64
|
+
{ from: /omega-active/g, to: 'end-active' },
|
|
65
|
+
{ from: /omega-id/g, to: 'end-id' },
|
|
66
|
+
|
|
67
|
+
// layout class props
|
|
68
|
+
{ from: /bottom-class=/g, to: 'block-end-class=' },
|
|
69
|
+
{ from: /left-class=/g, to: 'start-class=' },
|
|
70
|
+
{ from: /right-class=/g, to: 'end-class=' },
|
|
71
|
+
|
|
72
|
+
// ── Prop value renames ────────────────────────────────────────────────
|
|
73
|
+
// icon-position values
|
|
74
|
+
{ from: /icon-position="left"/g, to: 'icon-position="start"' },
|
|
75
|
+
{ from: /icon-position="right"/g, to: 'icon-position="end"' },
|
|
76
|
+
{ from: /icon-position="top"/g, to: 'icon-position="blockStart"' },
|
|
77
|
+
{ from: /icon-position="bottom"/g, to: 'icon-position="blockEnd"' },
|
|
78
|
+
// sidebar-position values
|
|
79
|
+
{ from: /sidebar-position="left"/g, to: 'sidebar-position="start"' },
|
|
80
|
+
{ from: /sidebar-position="right"/g, to: 'sidebar-position="end"' },
|
|
81
|
+
|
|
82
|
+
// ── Event renames ─────────────────────────────────────────────────────
|
|
83
|
+
{ from: /@alpha-clicked/g, to: '@start-clicked' },
|
|
84
|
+
{ from: /@omega-clicked/g, to: '@end-clicked' },
|
|
85
|
+
],
|
|
86
|
+
};
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
// Mapping: --dt-size-{stop} → --dt-spacing-{suffix}
|
|
2
|
+
// For tokens used in spacing context (padding, margin, gap, inset, etc.)
|
|
3
|
+
const SPACING_MAP = {
|
|
4
|
+
0: 'spacing-0', // 0px
|
|
5
|
+
50: 'spacing-1', // 0.5px → 1px (nearest non-subpixel)
|
|
6
|
+
100: 'spacing-1', // 1px
|
|
7
|
+
200: 'spacing-25', // 2px
|
|
8
|
+
300: 'spacing-50', // 4px
|
|
9
|
+
350: 'spacing-75', // 6px
|
|
10
|
+
400: 'spacing-100', // 8px
|
|
11
|
+
450: 'spacing-150', // 12px
|
|
12
|
+
500: 'spacing-200', // 16px
|
|
13
|
+
525: 'spacing-250', // 20px
|
|
14
|
+
550: 'spacing-300', // 24px
|
|
15
|
+
600: 'spacing-400', // 32px
|
|
16
|
+
625: 'spacing-525', // 42px
|
|
17
|
+
650: 'spacing-600', // 48px
|
|
18
|
+
700: 'spacing-800', // 64px
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// Mapping: --dt-size-{stop} → --dt-layout-{suffix}
|
|
22
|
+
// For tokens used in layout context (width, height, etc.)
|
|
23
|
+
// Exact matches are labeled; nearest-neighbor approximations note the delta.
|
|
24
|
+
const LAYOUT_MAP = {
|
|
25
|
+
// Exact scale matches
|
|
26
|
+
500: '25', // 16px
|
|
27
|
+
600: '50', // 32px
|
|
28
|
+
650: '75', // 48px
|
|
29
|
+
700: '100', // 64px
|
|
30
|
+
750: '150', // 96px
|
|
31
|
+
800: '200', // 128px
|
|
32
|
+
850: '300', // 192px
|
|
33
|
+
900: '400', // 256px
|
|
34
|
+
950: '600', // 384px
|
|
35
|
+
1000: '800', // 512px
|
|
36
|
+
1050: '1200', // 768px
|
|
37
|
+
1100: '1600', // 1024px
|
|
38
|
+
// Nearest-neighbor (no exact match in --dt-layout-* scale)
|
|
39
|
+
825: '250', // 164px → 160px (Δ4px)
|
|
40
|
+
875: '350', // 216px → 224px (Δ8px)
|
|
41
|
+
905: '400', // 264px → 256px (Δ8px)
|
|
42
|
+
925: '500', // 332px → 320px (Δ12px)
|
|
43
|
+
975: '700', // 464px → 448px (Δ16px)
|
|
44
|
+
1020: '1000', // 628px → 640px (Δ12px)
|
|
45
|
+
1040: '1200', // 764px → 768px (Δ4px)
|
|
46
|
+
1060: '1300', // 828px → 832px (Δ4px)
|
|
47
|
+
1080: '1400', // 912px → 896px (Δ16px)
|
|
48
|
+
// Previously missing — these old stops silently passed through
|
|
49
|
+
720: '100', // 72px → 64px (Δ8px)
|
|
50
|
+
730: '125', // 84px → 80px (Δ4px)
|
|
51
|
+
760: '150', // 102px → 96px (Δ6px)
|
|
52
|
+
775: '175', // 114px → 112px (Δ2px)
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// Tokens that exceed the --dt-layout-* scale (max 1024px at layout-1600).
|
|
56
|
+
// Converted to raw rem values with a TODO comment for future token replacement.
|
|
57
|
+
const RAW_FALLBACK = {
|
|
58
|
+
1115: '71.25rem', // 1140px
|
|
59
|
+
1120: '79.25rem', // 1268px
|
|
60
|
+
1125: '80rem', // 1280px
|
|
61
|
+
1130: '83.75rem', // 1340px
|
|
62
|
+
1150: '96rem', // 1536px
|
|
63
|
+
1200: '128rem', // 2048px
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// Valid stops for semantic border and radius tokens
|
|
67
|
+
const BORDER_STOPS = new Set([0, 50, 100, 150, 200, 300, 400]);
|
|
68
|
+
const RADIUS_STOPS = new Set([0, 100, 200, 300, 350, 400, 450, 500, 600]);
|
|
69
|
+
|
|
70
|
+
// ── Replacer factories ─────────────────────────────────────────────────────
|
|
71
|
+
|
|
72
|
+
function spacingReplacer (match, pre, stop, suffix) {
|
|
73
|
+
const token = SPACING_MAP[Number(stop)];
|
|
74
|
+
return token ? `${pre}var(--dt-${token}${suffix || ''})` : match;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function layoutReplacer (match, pre, stop, suffix) {
|
|
78
|
+
const s = Number(stop);
|
|
79
|
+
if (LAYOUT_MAP[s]) return `${pre}var(--dt-layout-${LAYOUT_MAP[s]}${suffix || ''})`;
|
|
80
|
+
if (RAW_FALLBACK[s]) {
|
|
81
|
+
return `${pre}${RAW_FALLBACK[s]} /* TODO: no --dt-layout-* equivalent for --dt-size-${s} — replace with a layout token when one is added */`;
|
|
82
|
+
}
|
|
83
|
+
return match;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function borderReplacer (match, pre, stop) {
|
|
87
|
+
const s = Number(stop);
|
|
88
|
+
return BORDER_STOPS.has(s) ? `${pre}var(--dt-size-border-${s})` : match;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function radiusReplacer (match, pre, stop) {
|
|
92
|
+
const s = Number(stop);
|
|
93
|
+
return RADIUS_STOPS.has(s) ? `${pre}var(--dt-size-radius-${s})` : match;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Spacing property names (physical + logical)
|
|
97
|
+
const SPACING_PROPS =
|
|
98
|
+
'padding(?:-(?:top|right|bottom|left|block(?:-(?:start|end))?|inline(?:-(?:start|end))?))?|' +
|
|
99
|
+
'margin(?:-(?:top|right|bottom|left|block(?:-(?:start|end))?|inline(?:-(?:start|end))?))?|' +
|
|
100
|
+
'gap|row-gap|column-gap|' +
|
|
101
|
+
'inset(?:-(?:block(?:-(?:start|end))?|inline(?:-(?:start|end))?))?|' +
|
|
102
|
+
// Custom properties whose name contains spacing-related keywords
|
|
103
|
+
// e.g. --badge-padding-x, --badge-gap, --badge-letter-spacing
|
|
104
|
+
'--[a-z0-9-]*(?:padding|margin|gap|spacing|inset|offset)[a-z0-9-]*';
|
|
105
|
+
|
|
106
|
+
// Layout property names (physical + logical)
|
|
107
|
+
const LAYOUT_PROPS =
|
|
108
|
+
'(?:min-|max-)?width|' +
|
|
109
|
+
'(?:min-|max-)?height|' +
|
|
110
|
+
'flex-basis|' +
|
|
111
|
+
'(?:min-|max-)?inline-size|' +
|
|
112
|
+
'(?:min-|max-)?block-size|' +
|
|
113
|
+
// Custom properties whose name contains layout-related keywords
|
|
114
|
+
// e.g. --badge-min-width
|
|
115
|
+
// Note: "height" is intentionally excluded — "line-height" custom props would misroute.
|
|
116
|
+
// Note: "radius" is handled by RADIUS_PROPS, not here.
|
|
117
|
+
'--[a-z0-9-]*(?:width|basis)[a-z0-9-]*';
|
|
118
|
+
|
|
119
|
+
// Border-width property names → --dt-size-border-*
|
|
120
|
+
// Matches border shorthand, border-width, directional border-*, outline, outline-width.
|
|
121
|
+
// Does NOT match border-color, border-style, border-image, or border-radius.
|
|
122
|
+
const BORDER_PROPS =
|
|
123
|
+
'border(?:-(?:top|right|bottom|left|block(?:-(?:start|end))?|inline(?:-(?:start|end))?))?(?:-width)?|' +
|
|
124
|
+
'outline(?:-width)?|' +
|
|
125
|
+
// Custom properties with "border-width" in name (e.g. --popover-border-width)
|
|
126
|
+
'--[a-z0-9-]*border-width[a-z0-9-]*';
|
|
127
|
+
|
|
128
|
+
// Border-radius property names → --dt-size-radius-*
|
|
129
|
+
const RADIUS_PROPS =
|
|
130
|
+
'border-radius|' +
|
|
131
|
+
'border-(?:top|bottom)-(?:left|right)-radius|' +
|
|
132
|
+
'border-(?:start|end)-(?:start|end)-radius|' +
|
|
133
|
+
// Custom properties with "radius" in name (e.g. --badge-radius, --notice-border-radius)
|
|
134
|
+
'--[a-z0-9-]*radius[a-z0-9-]*';
|
|
135
|
+
|
|
136
|
+
export default {
|
|
137
|
+
description:
|
|
138
|
+
'Migrates --dt-size-* tokens based on CSS property context.\n' +
|
|
139
|
+
'- Border properties (border, border-width, outline) → var(--dt-size-border-*)\n\t' +
|
|
140
|
+
'eg. border: var(--dt-size-100) solid → border: var(--dt-size-border-100) solid\n' +
|
|
141
|
+
'- Border-radius properties → var(--dt-size-radius-*)\n\t' +
|
|
142
|
+
'eg. border-radius: var(--dt-size-300) → border-radius: var(--dt-size-radius-300)\n' +
|
|
143
|
+
'- Spacing properties (padding, margin, gap, inset) → var(--dt-spacing-*)\n\t' +
|
|
144
|
+
'eg. padding: var(--dt-size-400) → padding: var(--dt-spacing-100)\n' +
|
|
145
|
+
'- Layout properties (width, height, min/max, flex-basis) → var(--dt-layout-*)\n\t' +
|
|
146
|
+
'eg. width: var(--dt-size-700) → width: var(--dt-layout-100)\n' +
|
|
147
|
+
'- Percentage tokens → var(--dt-layout-*-percent)\n\t' +
|
|
148
|
+
'eg. var(--dt-size-100-percent) → var(--dt-layout-100-percent)\n' +
|
|
149
|
+
'- Tokens exceeding the layout scale (>1024px) are converted to raw rem with a TODO comment.\n' +
|
|
150
|
+
'- Also converts calc(var(--dt-spacing-*) * -1) → var(--dt-spacing-*-negative).\n' +
|
|
151
|
+
'- Unmapped tokens pass through unchanged — the lint rule will flag them.\n',
|
|
152
|
+
patterns: ['**/*.{css,less,scss,sass,styl,html,vue,md,js,ts,jsx,tsx}'],
|
|
153
|
+
globbyConfig: {
|
|
154
|
+
ignore: ['**/dialtone_migration_helper/tests/**'],
|
|
155
|
+
},
|
|
156
|
+
expressions: [
|
|
157
|
+
// Border-width context → --dt-size-border-* (must run before layout to win --*-border-width* conflicts)
|
|
158
|
+
{
|
|
159
|
+
from: new RegExp(
|
|
160
|
+
`((?:${BORDER_PROPS})\\s*:[^;]*?)var\\(--dt-size-([0-9]+)\\)`,
|
|
161
|
+
'gm',
|
|
162
|
+
),
|
|
163
|
+
to: borderReplacer,
|
|
164
|
+
},
|
|
165
|
+
// Border-radius context → --dt-size-radius-* (must run before layout to win --*-radius* conflicts)
|
|
166
|
+
{
|
|
167
|
+
from: new RegExp(
|
|
168
|
+
`((?:${RADIUS_PROPS})\\s*:[^;]*?)var\\(--dt-size-([0-9]+)\\)`,
|
|
169
|
+
'gm',
|
|
170
|
+
),
|
|
171
|
+
to: radiusReplacer,
|
|
172
|
+
},
|
|
173
|
+
// Percentage tokens → --dt-layout-*-percent (context-independent, straight prefix swap)
|
|
174
|
+
{
|
|
175
|
+
from: /var\(--dt-size-([0-9]+)-percent\)/g,
|
|
176
|
+
to: (match, stop) => `var(--dt-layout-${stop}-percent)`,
|
|
177
|
+
},
|
|
178
|
+
// Spacing-context properties → --dt-spacing-*
|
|
179
|
+
{
|
|
180
|
+
from: new RegExp(
|
|
181
|
+
`((?:${SPACING_PROPS})\\s*:[^;]*?)var\\(--dt-size-([0-9]+)(-negative|-percent)?\\)`,
|
|
182
|
+
'gm',
|
|
183
|
+
),
|
|
184
|
+
to: spacingReplacer,
|
|
185
|
+
},
|
|
186
|
+
// Layout-context properties → --dt-layout-* (or raw rem for out-of-scale values)
|
|
187
|
+
{
|
|
188
|
+
from: new RegExp(
|
|
189
|
+
`((?:${LAYOUT_PROPS})\\s*:[^;]*?)var\\(--dt-size-([0-9]+)(-negative)?\\)`,
|
|
190
|
+
'gm',
|
|
191
|
+
),
|
|
192
|
+
to: layoutReplacer,
|
|
193
|
+
},
|
|
194
|
+
// Default: remaining --dt-size-* not matched by a known property context → layout map
|
|
195
|
+
{
|
|
196
|
+
from: /var\(--dt-size-([0-9]+)(-negative|-percent)?\)/g,
|
|
197
|
+
to: (match, stop, suffix) => {
|
|
198
|
+
const s = Number(stop);
|
|
199
|
+
if (LAYOUT_MAP[s]) return `var(--dt-layout-${LAYOUT_MAP[s]}${suffix || ''})`;
|
|
200
|
+
if (RAW_FALLBACK[s]) {
|
|
201
|
+
return `${RAW_FALLBACK[s]} /* TODO: no --dt-layout-* equivalent for --dt-size-${s} — replace with a layout token when one is added */`;
|
|
202
|
+
}
|
|
203
|
+
return match;
|
|
204
|
+
},
|
|
205
|
+
},
|
|
206
|
+
// Cleanup: calc(var(--dt-spacing-*) * -1) → var(--dt-spacing-*-negative)
|
|
207
|
+
{
|
|
208
|
+
from: /calc\(var\(--dt-spacing-([a-z0-9]+)\)\s*\*\s*-1\)/g,
|
|
209
|
+
to: (match, stop) => `var(--dt-spacing-${stop}-negative)`,
|
|
210
|
+
},
|
|
211
|
+
],
|
|
212
|
+
};
|