@atlaskit/eslint-plugin-platform 2.9.1 → 2.9.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.
Files changed (35) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/cjs/index.js +15 -3
  3. package/dist/cjs/rules/compiled/expand-motion-shorthand/index.js +281 -0
  4. package/dist/cjs/rules/compiled/no-css-prop-in-object-spread/index.js +162 -0
  5. package/dist/cjs/rules/compiled/use-motion-token-values/index.js +506 -0
  6. package/dist/cjs/rules/editor-example-type-import-required/index.js +321 -0
  7. package/dist/cjs/rules/no-xcss-in-cx/index.js +221 -0
  8. package/dist/cjs/rules/visit-example-type-import-required/index.js +23 -13
  9. package/dist/es2019/index.js +15 -3
  10. package/dist/es2019/rules/compiled/expand-motion-shorthand/index.js +239 -0
  11. package/dist/es2019/rules/compiled/no-css-prop-in-object-spread/index.js +136 -0
  12. package/dist/es2019/rules/compiled/use-motion-token-values/index.js +444 -0
  13. package/dist/es2019/rules/editor-example-type-import-required/index.js +286 -0
  14. package/dist/es2019/rules/no-xcss-in-cx/index.js +187 -0
  15. package/dist/es2019/rules/visit-example-type-import-required/index.js +23 -14
  16. package/dist/esm/index.js +15 -3
  17. package/dist/esm/rules/compiled/expand-motion-shorthand/index.js +275 -0
  18. package/dist/esm/rules/compiled/no-css-prop-in-object-spread/index.js +156 -0
  19. package/dist/esm/rules/compiled/use-motion-token-values/index.js +499 -0
  20. package/dist/esm/rules/editor-example-type-import-required/index.js +314 -0
  21. package/dist/esm/rules/no-xcss-in-cx/index.js +216 -0
  22. package/dist/esm/rules/visit-example-type-import-required/index.js +23 -13
  23. package/dist/types/index.d.ts +282 -243
  24. package/dist/types/rules/compiled/expand-motion-shorthand/index.d.ts +3 -0
  25. package/dist/types/rules/compiled/no-css-prop-in-object-spread/index.d.ts +3 -0
  26. package/dist/types/rules/compiled/use-motion-token-values/index.d.ts +3 -0
  27. package/dist/types/rules/editor-example-type-import-required/index.d.ts +4 -0
  28. package/dist/types/rules/no-xcss-in-cx/index.d.ts +31 -0
  29. package/dist/types-ts4.5/index.d.ts +226 -211
  30. package/dist/types-ts4.5/rules/compiled/expand-motion-shorthand/index.d.ts +3 -0
  31. package/dist/types-ts4.5/rules/compiled/no-css-prop-in-object-spread/index.d.ts +3 -0
  32. package/dist/types-ts4.5/rules/compiled/use-motion-token-values/index.d.ts +3 -0
  33. package/dist/types-ts4.5/rules/editor-example-type-import-required/index.d.ts +4 -0
  34. package/dist/types-ts4.5/rules/no-xcss-in-cx/index.d.ts +31 -0
  35. package/package.json +2 -1
@@ -0,0 +1,499 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
3
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
4
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
5
+ import tokenDefaultValues from '@atlaskit/tokens/token-default-values';
6
+ var DURATION_TOKEN_NAMES = ['motion.duration.instant', 'motion.duration.xxshort', 'motion.duration.xshort', 'motion.duration.short', 'motion.duration.medium', 'motion.duration.long', 'motion.duration.xlong', 'motion.duration.xxlong'];
7
+ function parseDurationMs(value) {
8
+ var ms = value.match(/^(\d+(?:\.\d+)?)ms$/);
9
+ if (ms) {
10
+ return parseFloat(ms[1]);
11
+ }
12
+ var s = value.match(/^(\d+(?:\.\d+)?)s$/);
13
+ if (s) {
14
+ return parseFloat(s[1]) * 1000;
15
+ }
16
+ return null;
17
+ }
18
+ var DURATION_TOKENS = DURATION_TOKEN_NAMES.map(function (name) {
19
+ var rawValue = tokenDefaultValues[name];
20
+ var ms = parseDurationMs(rawValue);
21
+ if (ms === null) {
22
+ throw new Error("use-motion-token-values: could not parse duration for token ".concat(name, ": ").concat(rawValue));
23
+ }
24
+ return {
25
+ ms: ms,
26
+ token: name
27
+ };
28
+ }).sort(function (a, b) {
29
+ return a.ms - b.ms;
30
+ });
31
+ var EASING_TOKEN_NAMES = ['motion.easing.in.practical', 'motion.easing.inout.bold', 'motion.easing.out.practical', 'motion.easing.out.bold'];
32
+ function parseCubicBezierParams(value) {
33
+ var match = value.match(/^cubic-bezier\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)\s*\)$/);
34
+ if (!match) {
35
+ return null;
36
+ }
37
+ return [parseFloat(match[1]), parseFloat(match[2]), parseFloat(match[3]), parseFloat(match[4])];
38
+ }
39
+ var EASING_TOKENS = EASING_TOKEN_NAMES.map(function (name) {
40
+ var rawValue = tokenDefaultValues[name];
41
+ var params = parseCubicBezierParams(rawValue);
42
+ if (!params) {
43
+ throw new Error("use-motion-token-values: could not parse cubic-bezier for token ".concat(name, ": ").concat(rawValue));
44
+ }
45
+ return {
46
+ value: rawValue,
47
+ token: name,
48
+ params: params
49
+ };
50
+ });
51
+
52
+ // Splits on top-level commas (outside function parens) — preserves cubic-bezier(...) commas.
53
+ function splitOnTopLevelCommas(value) {
54
+ var parts = [];
55
+ var depth = 0;
56
+ var current = '';
57
+ var _iterator = _createForOfIteratorHelper(value),
58
+ _step;
59
+ try {
60
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
61
+ var ch = _step.value;
62
+ if (ch === '(') {
63
+ depth++;
64
+ current += ch;
65
+ } else if (ch === ')') {
66
+ depth--;
67
+ current += ch;
68
+ } else if (ch === ',' && depth === 0) {
69
+ parts.push(current.trim());
70
+ current = '';
71
+ } else {
72
+ current += ch;
73
+ }
74
+ }
75
+ } catch (err) {
76
+ _iterator.e(err);
77
+ } finally {
78
+ _iterator.f();
79
+ }
80
+ if (current.trim().length > 0) {
81
+ parts.push(current.trim());
82
+ }
83
+ return parts;
84
+ }
85
+ var DURATION_PROPERTIES = new Set(['transitionDuration', 'animationDuration']);
86
+ var EASING_PROPERTIES = new Set(['transitionTimingFunction', 'animationTimingFunction']);
87
+
88
+ // Explicit semantic mappings for CSS keyword easings to motion tokens.
89
+ // Pinned by design intent, confirmed with design system team (Alex + Akshay).
90
+ var CSS_KEYWORD_EASING_TOKEN_MAP = {
91
+ ease: 'motion.easing.out.practical',
92
+ 'ease-out': 'motion.easing.out.practical',
93
+ 'ease-in': 'motion.easing.in.practical',
94
+ 'ease-in-out': 'motion.easing.inout.bold'
95
+ // linear (0,0,1,1) — warn only, no autofix (per Akshay: too generic, no good token match)
96
+ };
97
+
98
+ // Non-curve easing values with no meaningful cubic-bezier representation — skip entirely
99
+ var SKIP_EASING_VALUES = new Set(['step-start', 'step-end', 'inherit', 'initial', 'unset', 'none']);
100
+ function euclideanDistance(a, b) {
101
+ return Math.sqrt(a.reduce(function (sum, val, i) {
102
+ return sum + Math.pow(val - b[i], 2);
103
+ }, 0));
104
+ }
105
+
106
+ // Maximum Euclidean distance for easing autofix — beyond this threshold, we report-only
107
+ var EASING_AUTOFIX_THRESHOLD = 0.5;
108
+ function findClosestEasingToken(params) {
109
+ var minDist = Infinity;
110
+ var closest = EASING_TOKENS[0];
111
+ var _iterator2 = _createForOfIteratorHelper(EASING_TOKENS),
112
+ _step2;
113
+ try {
114
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
115
+ var entry = _step2.value;
116
+ var dist = euclideanDistance(params, entry.params);
117
+ if (dist < minDist) {
118
+ minDist = dist;
119
+ closest = entry;
120
+ }
121
+ }
122
+ } catch (err) {
123
+ _iterator2.e(err);
124
+ } finally {
125
+ _iterator2.f();
126
+ }
127
+ if (minDist > EASING_AUTOFIX_THRESHOLD) {
128
+ return null;
129
+ }
130
+ return {
131
+ token: closest.token,
132
+ value: closest.value,
133
+ dist: minDist
134
+ };
135
+ }
136
+ function findClosestDurationTokens(ms) {
137
+ var exact = DURATION_TOKENS.find(function (t) {
138
+ return t.ms === ms;
139
+ });
140
+ if (exact) {
141
+ return [exact];
142
+ }
143
+ var minDist = Infinity;
144
+ var _iterator3 = _createForOfIteratorHelper(DURATION_TOKENS),
145
+ _step3;
146
+ try {
147
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
148
+ var entry = _step3.value;
149
+ var dist = Math.abs(entry.ms - ms);
150
+ if (dist < minDist) {
151
+ minDist = dist;
152
+ }
153
+ }
154
+ } catch (err) {
155
+ _iterator3.e(err);
156
+ } finally {
157
+ _iterator3.f();
158
+ }
159
+ var closest = DURATION_TOKENS.filter(function (t) {
160
+ return Math.abs(t.ms - ms) === minDist;
161
+ });
162
+ return closest;
163
+ }
164
+ export var useMotionTokenValues = {
165
+ meta: {
166
+ type: 'suggestion',
167
+ fixable: 'code',
168
+ docs: {
169
+ url: 'https://bitbucket.org/atlassian/atlassian-frontend-monorepo/src/master/platform/packages/platform/eslint-plugin/src/rules/compiled/use-motion-token-values/'
170
+ },
171
+ messages: {
172
+ useMotionDurationToken: "Use a motion duration token instead of the hard-coded value '{{ value }}'. Replace with {{ suggestion }}.",
173
+ useMotionDurationTokenNearest: "No exact token match for '{{ value }}'. Nearest: {{ suggestion1 }} or {{ suggestion2 }}.",
174
+ useMotionEasingToken: "Use a motion easing token instead of the hard-coded value '{{ value }}'. Replace with {{ suggestion }}.",
175
+ useMotionEasingTokenUnknown: "Use a motion easing token from @atlaskit/tokens instead of the hard-coded value '{{ value }}'."
176
+ }
177
+ },
178
+ create: function create(context) {
179
+ var tokensImportNode = null;
180
+ var hasTokenSpecifier = false;
181
+ function buildTokenCall(tokenName, fallback) {
182
+ return "token('".concat(tokenName, "', '").concat(fallback, "')");
183
+ }
184
+ function getImportFix(fixer) {
185
+ var _context$sourceCode;
186
+ if (hasTokenSpecifier) {
187
+ return [];
188
+ }
189
+ if (tokensImportNode) {
190
+ // @atlaskit/tokens is imported but without `token` — add `token` to existing import
191
+ var lastSpecifier = tokensImportNode.specifiers[tokensImportNode.specifiers.length - 1];
192
+ if (lastSpecifier) {
193
+ return [fixer.insertTextAfter(lastSpecifier, ', token')];
194
+ }
195
+ // Empty import — replace the whole declaration
196
+ return [fixer.replaceText(tokensImportNode, "import { token } from '@atlaskit/tokens';")];
197
+ }
198
+ var sourceCode = (_context$sourceCode = context.sourceCode) !== null && _context$sourceCode !== void 0 ? _context$sourceCode : context.getSourceCode();
199
+ var programBody = sourceCode.ast.body;
200
+ // Insert after the last existing import, or at top if no imports exist
201
+ var lastImport = _toConsumableArray(programBody).reverse().find(function (n) {
202
+ return n.type === 'ImportDeclaration';
203
+ });
204
+ if (lastImport) {
205
+ return [fixer.insertTextAfter(lastImport, "\nimport { token } from '@atlaskit/tokens';")];
206
+ }
207
+ if (programBody.length > 0) {
208
+ return [fixer.insertTextBefore(programBody[0], "import { token } from '@atlaskit/tokens';\n")];
209
+ }
210
+ return [];
211
+ }
212
+
213
+ // Returns autofix string for a single duration value, or null if ambiguous (equidistant)
214
+ function resolveDurationToken(value) {
215
+ var ms = parseDurationMs(value);
216
+ if (ms === null) {
217
+ return null;
218
+ }
219
+ var result = findClosestDurationTokens(ms);
220
+ if (result.length === 1) {
221
+ return buildTokenCall(result[0].token, value);
222
+ }
223
+ return null;
224
+ }
225
+ function handleDurationProperty(node, rawValue) {
226
+ var segments = splitOnTopLevelCommas(rawValue);
227
+
228
+ // Single value path keeps the existing equidistant message
229
+ if (segments.length === 1) {
230
+ var ms = parseDurationMs(rawValue);
231
+ if (ms === null) {
232
+ return;
233
+ }
234
+ var result = findClosestDurationTokens(ms);
235
+ if (result.length === 1) {
236
+ var suggestion = buildTokenCall(result[0].token, rawValue);
237
+ context.report({
238
+ node: node,
239
+ messageId: 'useMotionDurationToken',
240
+ data: {
241
+ value: rawValue,
242
+ suggestion: suggestion
243
+ },
244
+ fix: function fix(fixer) {
245
+ return [].concat(_toConsumableArray(getImportFix(fixer)), [fixer.replaceText(node.value, suggestion)]);
246
+ }
247
+ });
248
+ } else {
249
+ var suggestion1 = buildTokenCall(result[0].token, rawValue);
250
+ var suggestion2 = buildTokenCall(result[1].token, rawValue);
251
+ context.report({
252
+ node: node,
253
+ messageId: 'useMotionDurationTokenNearest',
254
+ data: {
255
+ value: rawValue,
256
+ suggestion1: "".concat(suggestion1, " (").concat(result[0].ms, "ms)"),
257
+ suggestion2: "".concat(suggestion2, " (").concat(result[1].ms, "ms)")
258
+ }
259
+ });
260
+ }
261
+ return;
262
+ }
263
+
264
+ // Multi-value path: every segment must resolve to a single token for autofix
265
+ var resolved = segments.map(resolveDurationToken);
266
+ if (resolved.some(function (s) {
267
+ return s === null;
268
+ })) {
269
+ return;
270
+ }
271
+ // Build a template literal: `${token(...)}, ${token(...)}`
272
+ var templateLiteral = '`' + resolved.map(function (s) {
273
+ return "${".concat(s, "}");
274
+ }).join(', ') + '`';
275
+ context.report({
276
+ node: node,
277
+ messageId: 'useMotionDurationToken',
278
+ data: {
279
+ value: rawValue,
280
+ suggestion: templateLiteral
281
+ },
282
+ fix: function fix(fixer) {
283
+ return [].concat(_toConsumableArray(getImportFix(fixer)), [fixer.replaceText(node.value, templateLiteral)]);
284
+ }
285
+ });
286
+ }
287
+
288
+ // Returns autofix string for a single easing value, or null if no token suggestion is possible
289
+ function resolveEasingToken(value) {
290
+ var trimmed = value.trim();
291
+ if (SKIP_EASING_VALUES.has(trimmed)) {
292
+ return null;
293
+ }
294
+ if (trimmed in CSS_KEYWORD_EASING_TOKEN_MAP) {
295
+ return buildTokenCall(CSS_KEYWORD_EASING_TOKEN_MAP[trimmed], trimmed);
296
+ }
297
+ // linear has no curve (0,0,1,1) — warn only, no autofix
298
+ if (trimmed === 'linear') {
299
+ return null;
300
+ }
301
+ if (trimmed.startsWith('linear(')) {
302
+ // linear() is used for spring animations — motion.easing.spring is experimental, skip
303
+ return null;
304
+ }
305
+ var params = parseCubicBezierParams(trimmed);
306
+ if (!params) {
307
+ return null;
308
+ }
309
+ var exact = EASING_TOKENS.find(function (t) {
310
+ return t.value === trimmed;
311
+ });
312
+ if (exact) {
313
+ return buildTokenCall(exact.token, trimmed);
314
+ }
315
+ var closest = findClosestEasingToken(params);
316
+ return closest ? buildTokenCall(closest.token, trimmed) : null;
317
+ }
318
+ function handleEasingProperty(node, rawValue) {
319
+ var segments = splitOnTopLevelCommas(rawValue);
320
+
321
+ // Multi-value path: resolve each segment, autofix only if all resolve cleanly
322
+ if (segments.length > 1) {
323
+ var resolved = segments.map(resolveEasingToken);
324
+ if (resolved.some(function (s) {
325
+ return s === null;
326
+ })) {
327
+ return;
328
+ }
329
+ var templateLiteral = '`' + resolved.map(function (s) {
330
+ return "${".concat(s, "}");
331
+ }).join(', ') + '`';
332
+ context.report({
333
+ node: node,
334
+ messageId: 'useMotionEasingToken',
335
+ data: {
336
+ value: rawValue,
337
+ suggestion: templateLiteral
338
+ },
339
+ fix: function fix(fixer) {
340
+ return [].concat(_toConsumableArray(getImportFix(fixer)), [fixer.replaceText(node.value, templateLiteral)]);
341
+ }
342
+ });
343
+ return;
344
+ }
345
+ var trimmed = rawValue.trim();
346
+ if (SKIP_EASING_VALUES.has(trimmed)) {
347
+ return;
348
+ }
349
+
350
+ // CSS keyword easings: convert to cubic-bezier equivalent and find closest token
351
+ if (trimmed in CSS_KEYWORD_EASING_TOKEN_MAP) {
352
+ var suggestion = buildTokenCall(CSS_KEYWORD_EASING_TOKEN_MAP[trimmed], trimmed);
353
+ context.report({
354
+ node: node,
355
+ messageId: 'useMotionEasingToken',
356
+ data: {
357
+ value: trimmed,
358
+ suggestion: suggestion
359
+ },
360
+ fix: function fix(fixer) {
361
+ return [].concat(_toConsumableArray(getImportFix(fixer)), [fixer.replaceText(node.value, suggestion)]);
362
+ }
363
+ });
364
+ return;
365
+ }
366
+ // linear has no curve (0,0,1,1) — warn only, no autofix
367
+ if (trimmed === 'linear') {
368
+ context.report({
369
+ node: node,
370
+ messageId: 'useMotionEasingTokenUnknown',
371
+ data: {
372
+ value: trimmed
373
+ }
374
+ });
375
+ return;
376
+ }
377
+ if (trimmed.startsWith('linear(')) {
378
+ // linear() is used for spring animations — motion.easing.spring is experimental, skip
379
+ return;
380
+ }
381
+ var params = parseCubicBezierParams(trimmed);
382
+ if (!params) {
383
+ context.report({
384
+ node: node,
385
+ messageId: 'useMotionEasingTokenUnknown',
386
+ data: {
387
+ value: rawValue
388
+ }
389
+ });
390
+ return;
391
+ }
392
+ var exact = EASING_TOKENS.find(function (t) {
393
+ return t.value === trimmed;
394
+ });
395
+ if (exact) {
396
+ var _suggestion = buildTokenCall(exact.token, rawValue);
397
+ context.report({
398
+ node: node,
399
+ messageId: 'useMotionEasingToken',
400
+ data: {
401
+ value: rawValue,
402
+ suggestion: _suggestion
403
+ },
404
+ fix: function fix(fixer) {
405
+ return [].concat(_toConsumableArray(getImportFix(fixer)), [fixer.replaceText(node.value, _suggestion)]);
406
+ }
407
+ });
408
+ return;
409
+ }
410
+ var closest = findClosestEasingToken(params);
411
+ if (closest) {
412
+ var _suggestion2 = buildTokenCall(closest.token, rawValue);
413
+ context.report({
414
+ node: node,
415
+ messageId: 'useMotionEasingToken',
416
+ data: {
417
+ value: rawValue,
418
+ suggestion: _suggestion2
419
+ },
420
+ fix: function fix(fixer) {
421
+ return [].concat(_toConsumableArray(getImportFix(fixer)), [fixer.replaceText(node.value, _suggestion2)]);
422
+ }
423
+ });
424
+ } else {
425
+ context.report({
426
+ node: node,
427
+ messageId: 'useMotionEasingTokenUnknown',
428
+ data: {
429
+ value: rawValue
430
+ }
431
+ });
432
+ }
433
+ }
434
+ function handleProperty(node) {
435
+ var key = node.key;
436
+ if (key.type !== 'Identifier') {
437
+ return;
438
+ }
439
+ var isDuration = DURATION_PROPERTIES.has(key.name);
440
+ var isEasing = EASING_PROPERTIES.has(key.name);
441
+ if (!isDuration && !isEasing) {
442
+ return;
443
+ }
444
+ var value = node.value;
445
+ if (value.type === 'TemplateLiteral') {
446
+ // Only handle no-interpolation template literals (e.g. `200ms`) — treat as string
447
+ var tl = value;
448
+ if (tl.expressions.length === 0 && tl.quasis.length === 1) {
449
+ var _tl$quasis$0$value$co;
450
+ var rawValue = (_tl$quasis$0$value$co = tl.quasis[0].value.cooked) !== null && _tl$quasis$0$value$co !== void 0 ? _tl$quasis$0$value$co : tl.quasis[0].value.raw;
451
+ if (isDuration) {
452
+ handleDurationProperty(node, rawValue);
453
+ } else {
454
+ handleEasingProperty(node, rawValue);
455
+ }
456
+ }
457
+ return;
458
+ }
459
+ if (value.type === 'CallExpression') {
460
+ var ce = value;
461
+ if (ce.callee.type === 'Identifier' && ce.callee.name === 'token') {
462
+ return;
463
+ }
464
+ return;
465
+ }
466
+ if (value.type === 'Literal') {
467
+ var lit = value;
468
+ var _rawValue;
469
+ if (typeof lit.value === 'string') {
470
+ _rawValue = lit.value;
471
+ } else if (typeof lit.value === 'number') {
472
+ // Treat bare numbers as ms
473
+ _rawValue = "".concat(lit.value, "ms");
474
+ } else {
475
+ return;
476
+ }
477
+ if (isDuration) {
478
+ handleDurationProperty(node, _rawValue);
479
+ } else {
480
+ handleEasingProperty(node, _rawValue);
481
+ }
482
+ }
483
+ }
484
+ return {
485
+ ImportDeclaration: function ImportDeclaration(node) {
486
+ if (node.source.value === '@atlaskit/tokens') {
487
+ tokensImportNode = node;
488
+ hasTokenSpecifier = node.specifiers.some(function (s) {
489
+ return s.type === 'ImportSpecifier' && s.local.name === 'token';
490
+ });
491
+ }
492
+ },
493
+ Property: function Property(node) {
494
+ handleProperty(node);
495
+ }
496
+ };
497
+ }
498
+ };
499
+ export default useMotionTokenValues;