@tempoxyz/ds 0.3.11 → 0.3.13

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 (212) hide show
  1. package/README.md +7 -6
  2. package/dist/docs/AGENTS.md +8 -5
  3. package/dist/docs/index.md +143 -135
  4. package/dist/docs/marketing/introduction/getting-started.md +241 -0
  5. package/dist/docs/{components → product/components}/accordion.md +8 -8
  6. package/dist/docs/{components → product/components}/address-card.md +5 -5
  7. package/dist/docs/{components → product/components}/agent-logo.md +5 -5
  8. package/dist/docs/{components → product/components}/alert-dialog.md +11 -11
  9. package/dist/docs/{components → product/components}/alert.md +11 -11
  10. package/dist/docs/{components → product/components}/amount-input.md +13 -13
  11. package/dist/docs/{components → product/components}/amount.md +8 -8
  12. package/dist/docs/{components → product/components}/app-shell.md +13 -13
  13. package/dist/docs/{components → product/components}/asset-chip.md +11 -11
  14. package/dist/docs/{components → product/components}/autocomplete.md +10 -9
  15. package/dist/docs/{components → product/components}/avatar.md +8 -8
  16. package/dist/docs/{components → product/components}/badge.md +9 -9
  17. package/dist/docs/{components → product/components}/badged-logo.md +6 -6
  18. package/dist/docs/{components → product/components}/banner.md +8 -8
  19. package/dist/docs/{components → product/components}/bar-chart.md +7 -7
  20. package/dist/docs/{components → product/components}/breadcrumbs.md +8 -8
  21. package/dist/docs/{components → product/components}/button-group.md +8 -8
  22. package/dist/docs/{components → product/components}/button.md +17 -17
  23. package/dist/docs/{components → product/components}/calendar.md +8 -8
  24. package/dist/docs/{components → product/components}/callout.md +5 -5
  25. package/dist/docs/{components → product/components}/checkbox-group.md +13 -13
  26. package/dist/docs/{components → product/components}/checkbox.md +12 -12
  27. package/dist/docs/{components → product/components}/choice-group.md +14 -14
  28. package/dist/docs/{components → product/components}/choicebox.md +9 -9
  29. package/dist/docs/{components → product/components}/code.md +5 -5
  30. package/dist/docs/{components → product/components}/combobox.md +9 -9
  31. package/dist/docs/{components → product/components}/container.md +7 -7
  32. package/dist/docs/{components → product/components}/copy-button.md +13 -13
  33. package/dist/docs/{components → product/components}/date-picker.md +11 -11
  34. package/dist/docs/{components → product/components}/dialog.md +17 -17
  35. package/dist/docs/{components → product/components}/drawer.md +11 -11
  36. package/dist/docs/{components → product/components}/empty.md +9 -9
  37. package/dist/docs/{components → product/components}/field.md +14 -14
  38. package/dist/docs/{components → product/components}/fieldset.md +6 -6
  39. package/dist/docs/{components → product/components}/frame.md +9 -9
  40. package/dist/docs/{components → product/components}/gauge.md +7 -7
  41. package/dist/docs/{components → product/components}/get-started-visual.md +4 -4
  42. package/dist/docs/{components → product/components}/grid.md +7 -7
  43. package/dist/docs/{components → product/components}/hero-visual.md +4 -4
  44. package/dist/docs/{components → product/components}/hex.md +9 -9
  45. package/dist/docs/{components → product/components}/icon-tile.md +8 -8
  46. package/dist/docs/{components → product/components}/identicon.md +7 -7
  47. package/dist/docs/{components → product/components}/inline.md +7 -7
  48. package/dist/docs/{components → product/components}/inset.md +8 -8
  49. package/dist/docs/{components → product/components}/kbd.md +8 -8
  50. package/dist/docs/{components → product/components}/list-group.md +24 -24
  51. package/dist/docs/{components → product/components}/loading-dots.md +8 -8
  52. package/dist/docs/{components → product/components}/menu.md +14 -14
  53. package/dist/docs/{components → product/components}/native-select.md +7 -7
  54. package/dist/docs/{components → product/components}/network-logo.md +7 -7
  55. package/dist/docs/{components → product/components}/number-field.md +8 -8
  56. package/dist/docs/{components → product/components}/otp-field.md +9 -9
  57. package/dist/docs/{components → product/components}/pagination.md +8 -8
  58. package/dist/docs/{components → product/components}/popover.md +11 -11
  59. package/dist/docs/{components → product/components}/progress.md +10 -10
  60. package/dist/docs/{components → product/components}/qr.md +8 -8
  61. package/dist/docs/{components → product/components}/radio-group.md +10 -10
  62. package/dist/docs/{components → product/components}/secret-value.md +8 -8
  63. package/dist/docs/{components → product/components}/select.md +13 -13
  64. package/dist/docs/{components → product/components}/separator.md +7 -7
  65. package/dist/docs/{components → product/components}/sidebar-menu.md +11 -11
  66. package/dist/docs/{components → product/components}/skeleton.md +9 -9
  67. package/dist/docs/{components → product/components}/slider.md +8 -8
  68. package/dist/docs/{components → product/components}/snippet.md +10 -10
  69. package/dist/docs/{components → product/components}/spinner.md +12 -12
  70. package/dist/docs/{components → product/components}/split-bar.md +5 -5
  71. package/dist/docs/{components → product/components}/split-button.md +11 -11
  72. package/dist/docs/{components → product/components}/stack.md +8 -8
  73. package/dist/docs/{components → product/components}/status-chip.md +7 -7
  74. package/dist/docs/{components → product/components}/status-indicator.md +6 -6
  75. package/dist/docs/{components → product/components}/status-row.md +7 -7
  76. package/dist/docs/{components → product/components}/stepper.md +9 -9
  77. package/dist/docs/{components → product/components}/success-hero.md +5 -5
  78. package/dist/docs/{components → product/components}/surface.md +11 -11
  79. package/dist/docs/{components → product/components}/switch.md +11 -11
  80. package/dist/docs/{components → product/components}/table.md +16 -16
  81. package/dist/docs/{components → product/components}/tabs.md +11 -11
  82. package/dist/docs/{components → product/components}/tempo-logo.md +4 -4
  83. package/dist/docs/{components → product/components}/text-input.md +14 -14
  84. package/dist/docs/{components → product/components}/textarea.md +7 -7
  85. package/dist/docs/{components → product/components}/toast.md +11 -11
  86. package/dist/docs/{components → product/components}/token-logo.md +16 -16
  87. package/dist/docs/{components → product/components}/token.md +10 -10
  88. package/dist/docs/{components → product/components}/tooltip.md +11 -11
  89. package/dist/docs/{components → product/components}/verification-code.md +4 -4
  90. package/dist/docs/{components → product/components}/visual.md +5 -5
  91. package/dist/docs/product/components.md +203 -0
  92. package/dist/docs/{foundations → product/foundations}/accessibility.md +16 -16
  93. package/dist/docs/{foundations → product/foundations}/agents.md +17 -17
  94. package/dist/docs/{foundations → product/foundations}/color.md +7 -7
  95. package/dist/docs/{foundations → product/foundations}/content/tone.md +7 -7
  96. package/dist/docs/{foundations → product/foundations}/content/voice.md +2 -2
  97. package/dist/docs/{foundations → product/foundations}/content/writing-style.md +8 -8
  98. package/dist/docs/{foundations → product/foundations}/iconography.md +11 -11
  99. package/dist/docs/{foundations → product/foundations}/intent.md +28 -28
  100. package/dist/docs/{foundations → product/foundations}/layout.md +22 -22
  101. package/dist/docs/product/foundations/linter.md +496 -0
  102. package/dist/docs/{foundations → product/foundations}/motion.md +7 -7
  103. package/dist/docs/{foundations → product/foundations}/radius-and-padding.md +3 -3
  104. package/dist/docs/{foundations → product/foundations}/typography.md +4 -4
  105. package/dist/docs/{introduction → product/introduction}/faq.md +22 -21
  106. package/dist/docs/{introduction → product/introduction}/getting-started.md +4 -4
  107. package/dist/docs/{patterns → product/patterns}/blockchain-values.md +20 -20
  108. package/dist/docs/{patterns → product/patterns}/dashboards.md +28 -28
  109. package/dist/docs/{patterns → product/patterns}/destructive-actions.md +16 -16
  110. package/dist/docs/{patterns → product/patterns}/empty-states.md +14 -14
  111. package/dist/docs/{patterns → product/patterns}/errors-and-validation.md +23 -23
  112. package/dist/docs/{patterns → product/patterns}/feedback-and-status.md +31 -31
  113. package/dist/docs/{patterns → product/patterns}/forms.md +24 -24
  114. package/dist/docs/{patterns → product/patterns}/loading.md +19 -19
  115. package/dist/docs/{patterns → product/patterns}/navigation.md +23 -23
  116. package/dist/docs/{patterns → product/patterns}/payments.md +20 -20
  117. package/dist/docs/{patterns → product/patterns}/responsive-layout.md +23 -23
  118. package/dist/docs/{patterns → product/patterns}/tables-and-lists.md +19 -19
  119. package/dist/docs/{products → product/products}/tempo-console.md +12 -12
  120. package/dist/docs/{products → product/products}/tempo-performance.md +11 -11
  121. package/dist/docs/{products → product/products}/tempo-wallet.md +12 -12
  122. package/dist/marketing/index.d.ts +4 -0
  123. package/dist/marketing/index.d.ts.map +1 -0
  124. package/dist/marketing/index.js +4 -0
  125. package/dist/marketing/index.js.map +1 -0
  126. package/dist/marketing/index.js.zyzz.json +1 -0
  127. package/dist/marketing/vars.d.ts +907 -0
  128. package/dist/marketing/vars.d.ts.map +1 -0
  129. package/dist/marketing/vars.js +15 -0
  130. package/dist/marketing/vars.js.map +1 -0
  131. package/dist/marketing/vars.js.zyzz.json +1 -0
  132. package/dist/marketing/zyzz.config.d.ts +4512 -0
  133. package/dist/marketing/zyzz.config.d.ts.map +1 -0
  134. package/dist/marketing/zyzz.config.js +63 -0
  135. package/dist/marketing/zyzz.config.js.map +1 -0
  136. package/dist/marketing/zyzz.config.js.zyzz.json +1 -0
  137. package/dist/oxlint/index.d.ts +12 -1
  138. package/dist/oxlint/index.d.ts.map +1 -1
  139. package/dist/oxlint/index.js +39 -1
  140. package/dist/oxlint/index.js.map +1 -1
  141. package/dist/oxlint/internal/Docs.d.ts +9 -0
  142. package/dist/oxlint/internal/Docs.d.ts.map +1 -0
  143. package/dist/oxlint/internal/Docs.js +15 -0
  144. package/dist/oxlint/internal/Docs.js.map +1 -0
  145. package/dist/oxlint/internal/Imports.d.ts +1 -1
  146. package/dist/oxlint/internal/Imports.d.ts.map +1 -1
  147. package/dist/oxlint/internal/Imports.js +2 -0
  148. package/dist/oxlint/internal/Imports.js.map +1 -1
  149. package/dist/oxlint/internal/Styles.d.ts +40 -0
  150. package/dist/oxlint/internal/Styles.d.ts.map +1 -0
  151. package/dist/oxlint/internal/Styles.js +194 -0
  152. package/dist/oxlint/internal/Styles.js.map +1 -0
  153. package/dist/oxlint/internal/Tokens.d.ts +16 -0
  154. package/dist/oxlint/internal/Tokens.d.ts.map +1 -0
  155. package/dist/oxlint/internal/Tokens.js +39 -0
  156. package/dist/oxlint/internal/Tokens.js.map +1 -0
  157. package/dist/oxlint/rules/NoCrossSurface.d.ts +2 -2
  158. package/dist/oxlint/rules/NoCrossSurface.js +3 -3
  159. package/dist/oxlint/rules/NoCrossSurface.js.map +1 -1
  160. package/dist/oxlint/rules/NoCustomValues.d.ts +11 -0
  161. package/dist/oxlint/rules/NoCustomValues.d.ts.map +1 -0
  162. package/dist/oxlint/rules/NoCustomValues.js +150 -0
  163. package/dist/oxlint/rules/NoCustomValues.js.map +1 -0
  164. package/dist/oxlint/rules/NoSingleKeyShortcuts.d.ts +11 -0
  165. package/dist/oxlint/rules/NoSingleKeyShortcuts.d.ts.map +1 -0
  166. package/dist/oxlint/rules/NoSingleKeyShortcuts.js +158 -0
  167. package/dist/oxlint/rules/NoSingleKeyShortcuts.js.map +1 -0
  168. package/dist/oxlint/rules/PreferComponent.d.ts +3 -2
  169. package/dist/oxlint/rules/PreferComponent.d.ts.map +1 -1
  170. package/dist/oxlint/rules/PreferComponent.js +11 -4
  171. package/dist/oxlint/rules/PreferComponent.js.map +1 -1
  172. package/dist/oxlint/rules/PreferLayout.d.ts +9 -0
  173. package/dist/oxlint/rules/PreferLayout.d.ts.map +1 -0
  174. package/dist/oxlint/rules/PreferLayout.js +90 -0
  175. package/dist/oxlint/rules/PreferLayout.js.map +1 -0
  176. package/dist/oxlint/rules/PreferProgress.d.ts +9 -0
  177. package/dist/oxlint/rules/PreferProgress.d.ts.map +1 -0
  178. package/dist/oxlint/rules/PreferProgress.js +43 -0
  179. package/dist/oxlint/rules/PreferProgress.js.map +1 -0
  180. package/dist/oxlint/rules/PreferSurface.d.ts +9 -0
  181. package/dist/oxlint/rules/PreferSurface.d.ts.map +1 -0
  182. package/dist/oxlint/rules/PreferSurface.js +55 -0
  183. package/dist/oxlint/rules/PreferSurface.js.map +1 -0
  184. package/dist/oxlint/rules/RequireAccessibleName.d.ts.map +1 -1
  185. package/dist/oxlint/rules/RequireAccessibleName.js +3 -1
  186. package/dist/oxlint/rules/RequireAccessibleName.js.map +1 -1
  187. package/dist/oxlint/rules/RequireScrollRegion.d.ts +11 -0
  188. package/dist/oxlint/rules/RequireScrollRegion.d.ts.map +1 -0
  189. package/dist/oxlint/rules/RequireScrollRegion.js +71 -0
  190. package/dist/oxlint/rules/RequireScrollRegion.js.map +1 -0
  191. package/dist/web/icons/index.js.zyzz.json +1 -0
  192. package/package.json +6 -1
  193. package/src/marketing/README.md +21 -0
  194. package/src/marketing/index.ts +3 -0
  195. package/src/marketing/vars.ts +751 -0
  196. package/src/marketing/zyzz.config.ts +376 -0
  197. package/src/oxlint/index.ts +40 -1
  198. package/src/oxlint/internal/Docs.ts +18 -0
  199. package/src/oxlint/internal/Imports.ts +2 -1
  200. package/src/oxlint/internal/Styles.ts +240 -0
  201. package/src/oxlint/internal/Tokens.ts +43 -0
  202. package/src/oxlint/rules/NoCrossSurface.ts +3 -3
  203. package/src/oxlint/rules/NoCustomValues.ts +170 -0
  204. package/src/oxlint/rules/NoSingleKeyShortcuts.ts +190 -0
  205. package/src/oxlint/rules/PreferComponent.ts +11 -4
  206. package/src/oxlint/rules/PreferLayout.ts +96 -0
  207. package/src/oxlint/rules/PreferProgress.ts +49 -0
  208. package/src/oxlint/rules/PreferSurface.ts +70 -0
  209. package/src/oxlint/rules/RequireAccessibleName.ts +3 -1
  210. package/src/oxlint/rules/RequireScrollRegion.ts +92 -0
  211. package/dist/docs/components.md +0 -203
  212. package/dist/docs/foundations/linter.md +0 -296
@@ -0,0 +1,150 @@
1
+ import * as Docs from '../internal/Docs.js';
2
+ import * as Styles from '../internal/Styles.js';
3
+ import * as Tokens from '../internal/Tokens.js';
4
+ // Sizes that also accept a container width.
5
+ const containers = /^(?:flexBasis|inlineSize|max(?:InlineSize|Width)|min(?:InlineSize|Width)|width)$/;
6
+ // The longhands that set each part of a shorthand with two, three, or four parts.
7
+ const sides = {
8
+ 2: ['Block', 'Inline'],
9
+ 3: ['Top', 'Inline', 'Bottom'],
10
+ 4: ['Top', 'Right', 'Bottom', 'Left'],
11
+ };
12
+ // Sizes and offsets, which accept spacing steps.
13
+ const sizes = /^(?:blockSize|bottom|flexBasis|height|inlineSize|inset\w*|left|max(?:BlockSize|Height|InlineSize|Width)|min(?:BlockSize|Height|InlineSize|Width)|right|textIndent|top|width)$/;
14
+ // Properties on the spacing scale.
15
+ const spacing = /^(?:columnGap|gap|margin\w*|padding\w*|rowGap|scrollMargin\w*|scrollPadding\w*)$/;
16
+ const urls = {
17
+ container: Docs.page('foundations/layout#widths'),
18
+ radius: Docs.page('foundations/radius-and-padding'),
19
+ spacing: Docs.page('foundations/layout#spacing'),
20
+ zIndex: Docs.page('foundations/linter#use-tokens-for-custom-values'),
21
+ };
22
+ // A length in px, or `undefined` for any other value.
23
+ function px(value) {
24
+ const match = /^(-?(?:\d*\.)?\d+)(px|rem)$/.exec(value);
25
+ if (!match?.[1])
26
+ return undefined;
27
+ return Number(match[1]) * (match[2] === 'rem' ? 16 : 1);
28
+ }
29
+ /**
30
+ * Reports a `!custom` value in a `style()` or `variants()` definition that equals a Web token:
31
+ * a px or rem length on a spacing, radius, size, or container property that equals a step of its
32
+ * scale, and a number on `zIndex` that equals a layer. The message names the token to use.
33
+ * A `!custom` value that no token equals, such as `'13px !custom'`, is the sanctioned escape
34
+ * hatch and does not report.
35
+ */
36
+ export const rule = {
37
+ meta: {
38
+ docs: { description: 'Use the Web token that a `!custom` length or layer equals.' },
39
+ messages: {
40
+ token: "'{{property}}' sets the custom value {{value}}, which equals a token. Use {{tokens}}. See {{url}}",
41
+ },
42
+ schema: [],
43
+ type: 'suggestion',
44
+ },
45
+ create(context) {
46
+ // The advice for a property and its value, or `undefined` when no token replaces it.
47
+ function advise(property, value) {
48
+ if (property === 'zIndex') {
49
+ if (!/^-?\d+$/.test(value))
50
+ return undefined;
51
+ const layer = Object.entries(Tokens.zIndex).find((entry) => entry[1] === Number(value));
52
+ if (!layer)
53
+ return undefined;
54
+ return { tokens: `the zIndex token '${layer[0]}'`, url: urls.zIndex };
55
+ }
56
+ if (property.endsWith('Radius')) {
57
+ const length = px(value);
58
+ if (length === undefined)
59
+ return undefined;
60
+ const step = Object.entries(Tokens.radius).find((entry) => entry[1] === length);
61
+ if (!step)
62
+ return undefined;
63
+ return { tokens: `the radius token '${step[0]}'`, url: urls.radius };
64
+ }
65
+ if (spacing.test(property)) {
66
+ const parts = value.split(/\s+/);
67
+ const lengths = parts.map((part) => (part === 'auto' ? 'auto' : px(part)));
68
+ if (lengths.some((length) => length === undefined))
69
+ return undefined;
70
+ if (!lengths.some((length) => typeof length === 'number' && length !== 0))
71
+ return undefined;
72
+ if (lengths.some((length) => typeof length === 'number' && !Tokens.spacing.includes(length)))
73
+ return undefined;
74
+ const keys = lengths.map((length) => typeof length === 'number' ? Tokens.key(length) : 'auto');
75
+ const longhands = (() => {
76
+ if (property === 'gap')
77
+ return ['rowGap', 'columnGap'];
78
+ const suffixes = sides[parts.length];
79
+ return suffixes?.map((suffix) => `${property}${suffix}`);
80
+ })();
81
+ if (parts.length === 1)
82
+ return { tokens: `the spacing token '${keys[0]}'`, url: urls.spacing };
83
+ if (!longhands || longhands.length !== parts.length)
84
+ return undefined;
85
+ return {
86
+ tokens: `spacing tokens on each side: ${longhands.map((longhand, index) => `${longhand} '${keys[index]}'`).join(', ')}`,
87
+ url: urls.spacing,
88
+ };
89
+ }
90
+ if (sizes.test(property)) {
91
+ const length = px(value);
92
+ if (length === undefined || length === 0)
93
+ return undefined;
94
+ if (Tokens.spacing.includes(length))
95
+ return {
96
+ tokens: `the spacing token '${Tokens.key(length)}'`,
97
+ url: urls.spacing,
98
+ };
99
+ if (containers.test(property) && Tokens.container.includes(length))
100
+ return {
101
+ tokens: `the container token '${Tokens.key(length)}'`,
102
+ url: urls.container,
103
+ };
104
+ }
105
+ return undefined;
106
+ }
107
+ function check(object) {
108
+ for (const property of object.properties) {
109
+ if (property.type !== 'Property')
110
+ continue;
111
+ if (property.value.type === 'ObjectExpression') {
112
+ check(property.value);
113
+ continue;
114
+ }
115
+ const name = Styles.key(property);
116
+ const node = property.value;
117
+ const custom = (node.type === 'Literal' &&
118
+ typeof node.value === 'string' &&
119
+ node.value.endsWith('!custom')) ||
120
+ (node.type === 'TemplateLiteral' &&
121
+ node.expressions.length === 0 &&
122
+ node.quasis
123
+ .map((quasi) => quasi.value.cooked ?? '')
124
+ .join('')
125
+ .endsWith('!custom')) ||
126
+ (name === 'zIndex' && node.type === 'Literal' && typeof node.value === 'number');
127
+ const value = Styles.text(node);
128
+ if (name === undefined || !custom || value === undefined)
129
+ continue;
130
+ const advice = advise(name, value);
131
+ if (advice)
132
+ context.report({
133
+ data: { property: name, value: context.sourceCode.getText(node), ...advice },
134
+ messageId: 'token',
135
+ node,
136
+ });
137
+ }
138
+ }
139
+ return {
140
+ CallExpression(node) {
141
+ if (!Styles.helper(node.callee))
142
+ return;
143
+ for (const argument of node.arguments.slice(0, 1))
144
+ if (argument.type === 'ObjectExpression')
145
+ check(argument);
146
+ },
147
+ };
148
+ },
149
+ };
150
+ //# sourceMappingURL=NoCustomValues.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NoCustomValues.js","sourceRoot":"","sources":["../../../src/oxlint/rules/NoCustomValues.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /** Finds single-key shortcuts that listen on the whole page. @module */
2
+ import type { Rule } from '@oxlint/plugins';
3
+ /**
4
+ * Reports a `keydown`, `keyup`, or `keypress` listener on `window` or `document` that compares
5
+ * `key` with one printable character, or `code` with a letter or digit key, without reading a
6
+ * modifier. A character key on the whole page fires while people type or dictate, which WCAG 2.1.4
7
+ * Character Key Shortcuts forbids unless people can turn it off or remap it. A handler that reads
8
+ * `metaKey`, `ctrlKey`, `altKey`, or `getModifierState` passes.
9
+ */
10
+ export declare const rule: Rule;
11
+ //# sourceMappingURL=NoSingleKeyShortcuts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NoSingleKeyShortcuts.d.ts","sourceRoot":"","sources":["../../../src/oxlint/rules/NoSingleKeyShortcuts.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,OAAO,KAAK,EAAU,IAAI,EAAS,MAAM,iBAAiB,CAAA;AAS1D;;;;;;GAMG;AACH,eAAO,MAAM,IAAI,EAAE,IA4KlB,CAAA"}
@@ -0,0 +1,158 @@
1
+ import * as Docs from '../internal/Docs.js';
2
+ const events = new Set(['keydown', 'keypress', 'keyup']);
3
+ // Hooks that return the function they receive.
4
+ const hooks = new Set(['useCallback', 'useEffectEvent', 'useEvent']);
5
+ const modifiers = new Set(['altKey', 'ctrlKey', 'getModifierState', 'metaKey']);
6
+ const targets = new Set(['document', 'globalThis', 'self', 'window']);
7
+ /**
8
+ * Reports a `keydown`, `keyup`, or `keypress` listener on `window` or `document` that compares
9
+ * `key` with one printable character, or `code` with a letter or digit key, without reading a
10
+ * modifier. A character key on the whole page fires while people type or dictate, which WCAG 2.1.4
11
+ * Character Key Shortcuts forbids unless people can turn it off or remap it. A handler that reads
12
+ * `metaKey`, `ctrlKey`, `altKey`, or `getModifierState` passes.
13
+ */
14
+ export const rule = {
15
+ meta: {
16
+ docs: { description: 'Require a modifier on page-wide keyboard shortcuts.' },
17
+ messages: {
18
+ shortcut: "'{{key}}' is a single-key shortcut on the whole page. Require a modifier, such as metaKey or ctrlKey, or let people turn it off or remap it (WCAG 2.1.4). Show it with 'Kbd' from '@tempoxyz/ds'. See {{url}}",
19
+ },
20
+ schema: [],
21
+ type: 'problem',
22
+ },
23
+ create(context) {
24
+ const url = Docs.page('foundations/accessibility#shortcuts');
25
+ // The character that `node` compares with a key, such as `k` for `'k'` or `'KeyK'`.
26
+ function character(node, property) {
27
+ if (node.type !== 'Literal' || typeof node.value !== 'string')
28
+ return undefined;
29
+ if (property === 'code')
30
+ return /^(?:Digit\d|Key[A-Z])$/.test(node.value) ? node.value : undefined;
31
+ return [...node.value].length === 1 && /\S/.test(node.value) ? node.value : undefined;
32
+ }
33
+ // `event.key` or `event.code`, also through `toLowerCase()` or `toUpperCase()`.
34
+ function read(node) {
35
+ if (node.type === 'CallExpression' &&
36
+ node.callee.type === 'MemberExpression' &&
37
+ node.callee.property.type === 'Identifier' &&
38
+ /^to(?:Lower|Upper)Case$/.test(node.callee.property.name))
39
+ return read(node.callee.object);
40
+ if (node.type !== 'MemberExpression' || node.computed || node.property.type !== 'Identifier')
41
+ return undefined;
42
+ return node.property.name === 'key' || node.property.name === 'code'
43
+ ? node.property.name
44
+ : undefined;
45
+ }
46
+ function resolve(node) {
47
+ if (node.type === 'ArrowFunctionExpression' || node.type === 'FunctionExpression')
48
+ return node;
49
+ if (node.type === 'CallExpression' &&
50
+ node.callee.type === 'Identifier' &&
51
+ hooks.has(node.callee.name) &&
52
+ node.arguments[0])
53
+ return resolve(node.arguments[0]);
54
+ if (node.type !== 'Identifier')
55
+ return undefined;
56
+ for (let scope = context.sourceCode.getScope(node); scope; scope = scope.upper) {
57
+ const variable = scope.set.get(node.name);
58
+ if (!variable)
59
+ continue;
60
+ const definition = variable.defs[0]?.node;
61
+ if (definition?.type === 'FunctionDeclaration')
62
+ return definition;
63
+ if (definition?.type === 'VariableDeclarator' && definition.init)
64
+ return resolve(definition.init);
65
+ return undefined;
66
+ }
67
+ return undefined;
68
+ }
69
+ function walk(node, fn) {
70
+ fn(node);
71
+ for (const field of context.sourceCode.visitorKeys[node.type] ?? []) {
72
+ const value = Reflect.get(node, field);
73
+ for (const child of Array.isArray(value) ? value : [value])
74
+ if (child && typeof child === 'object' && 'type' in child)
75
+ walk(child, fn);
76
+ }
77
+ }
78
+ function check(handler) {
79
+ const found = [];
80
+ let modified = false;
81
+ walk(handler, (node) => {
82
+ if (node.type === 'MemberExpression' &&
83
+ node.property.type === 'Identifier' &&
84
+ modifiers.has(node.property.name))
85
+ modified = true;
86
+ if (node.type === 'BinaryExpression' && ['!=', '!==', '==', '==='].includes(node.operator))
87
+ for (const [left, right] of [
88
+ [node.left, node.right],
89
+ [node.right, node.left],
90
+ ]) {
91
+ const property = read(left);
92
+ const value = property && character(right, property);
93
+ if (value)
94
+ found.push({ character: value, node: right });
95
+ }
96
+ if (node.type === 'SwitchStatement') {
97
+ const property = read(node.discriminant);
98
+ if (property)
99
+ for (const entry of node.cases) {
100
+ const value = entry.test && character(entry.test, property);
101
+ if (value && entry.test)
102
+ found.push({ character: value, node: entry.test });
103
+ }
104
+ }
105
+ if (node.type === 'CallExpression' &&
106
+ node.callee.type === 'MemberExpression' &&
107
+ node.callee.property.type === 'Identifier' &&
108
+ node.callee.property.name === 'includes' &&
109
+ node.callee.object.type === 'ArrayExpression' &&
110
+ node.arguments[0]) {
111
+ const property = read(node.arguments[0]);
112
+ if (property)
113
+ for (const item of node.callee.object.elements) {
114
+ const value = item && character(item, property);
115
+ if (value && item)
116
+ found.push({ character: value, node: item });
117
+ }
118
+ }
119
+ });
120
+ if (modified)
121
+ return;
122
+ for (const entry of found)
123
+ context.report({
124
+ data: { key: entry.character, url },
125
+ messageId: 'shortcut',
126
+ node: entry.node,
127
+ });
128
+ }
129
+ return {
130
+ CallExpression(node) {
131
+ const callee = node.callee;
132
+ if (callee.type !== 'MemberExpression' ||
133
+ callee.property.type !== 'Identifier' ||
134
+ callee.property.name !== 'addEventListener')
135
+ return;
136
+ const target = (() => {
137
+ if (callee.object.type === 'Identifier')
138
+ return callee.object.name;
139
+ if (callee.object.type === 'MemberExpression' &&
140
+ callee.object.property.type === 'Identifier')
141
+ return callee.object.property.name;
142
+ return undefined;
143
+ })();
144
+ const [event, listener] = node.arguments;
145
+ if (!target || !(targets.has(target) || target === 'body'))
146
+ return;
147
+ if (event?.type !== 'Literal' ||
148
+ typeof event.value !== 'string' ||
149
+ !events.has(event.value))
150
+ return;
151
+ const handler = listener && resolve(listener);
152
+ if (handler)
153
+ check(handler);
154
+ },
155
+ };
156
+ },
157
+ };
158
+ //# sourceMappingURL=NoSingleKeyShortcuts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NoSingleKeyShortcuts.js","sourceRoot":"","sources":["../../../src/oxlint/rules/NoSingleKeyShortcuts.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,9 @@
1
1
  /** Points native HTML controls and structures at the Web components that replace them. @module */
2
2
  import type { Rule } from '@oxlint/plugins';
3
3
  /**
4
- * Reports a native element that a `@tempoxyz/ds` component replaces, such as `<button>` or
5
- * `<input type="checkbox">`. Elements inside a `render` prop are skipped, since the component that
4
+ * Reports a native element that a `@tempoxyz/ds` component replaces, such as `<button>`,
5
+ * `<input type="checkbox">`, or a `<dl>` of labels and values. The message links the docs page of
6
+ * the component. Elements inside a `render` prop are skipped, since the component that
6
7
  * receives them supplies the styles.
7
8
  */
8
9
  export declare const rule: Rule;
@@ -1 +1 @@
1
- {"version":3,"file":"PreferComponent.d.ts","sourceRoot":"","sources":["../../../src/oxlint/rules/PreferComponent.ts"],"names":[],"mappings":"AAAA,kGAAkG;AAClG,OAAO,KAAK,EAAU,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAmCnD;;;;GAIG;AACH,eAAO,MAAM,IAAI,EAAE,IA+DlB,CAAA;AAED,MAAM,CAAC,OAAO,WAAW,IAAI,CAAC;IAC5B,0CAA0C;IAC1C,KAAK,OAAO,GAAG;QACb,qFAAqF;QACrF,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAA;KACtC,CAAA;CACF"}
1
+ {"version":3,"file":"PreferComponent.d.ts","sourceRoot":"","sources":["../../../src/oxlint/rules/PreferComponent.ts"],"names":[],"mappings":"AAAA,kGAAkG;AAClG,OAAO,KAAK,EAAU,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAqCnD;;;;;GAKG;AACH,eAAO,MAAM,IAAI,EAAE,IAmElB,CAAA;AAED,MAAM,CAAC,OAAO,WAAW,IAAI,CAAC;IAC5B,0CAA0C;IAC1C,KAAK,OAAO,GAAG;QACb,qFAAqF;QACrF,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAA;KACtC,CAAA;CACF"}
@@ -1,8 +1,10 @@
1
+ import * as Docs from '../internal/Docs.js';
1
2
  // Each element maps to the component that renders it with Tempo styles, states, and semantics.
2
3
  const elements = {
3
4
  button: 'Button',
4
5
  details: 'Accordion',
5
6
  dialog: 'Dialog',
7
+ dl: 'ListGroup',
6
8
  fieldset: 'Fieldset',
7
9
  hr: 'Separator',
8
10
  kbd: 'Kbd',
@@ -30,8 +32,9 @@ const inputs = {
30
32
  url: 'TextInput',
31
33
  };
32
34
  /**
33
- * Reports a native element that a `@tempoxyz/ds` component replaces, such as `<button>` or
34
- * `<input type="checkbox">`. Elements inside a `render` prop are skipped, since the component that
35
+ * Reports a native element that a `@tempoxyz/ds` component replaces, such as `<button>`,
36
+ * `<input type="checkbox">`, or a `<dl>` of labels and values. The message links the docs page of
37
+ * the component. Elements inside a `render` prop are skipped, since the component that
35
38
  * receives them supplies the styles.
36
39
  */
37
40
  export const rule = {
@@ -40,7 +43,7 @@ export const rule = {
40
43
  description: 'Prefer `@tempoxyz/ds` components over the native elements they replace.',
41
44
  },
42
45
  messages: {
43
- component: "Use '{{component}}' from '@tempoxyz/ds' instead of <{{element}}>.",
46
+ component: "Use '{{component}}' from '@tempoxyz/ds' instead of <{{element}}>. See {{url}}",
44
47
  },
45
48
  schema: [
46
49
  {
@@ -81,7 +84,11 @@ export const rule = {
81
84
  const replacement = component(node);
82
85
  if (replacement)
83
86
  context.report({
84
- data: { component: replacement, element: node.name.name },
87
+ data: {
88
+ component: replacement,
89
+ element: node.name.name,
90
+ url: Docs.component(replacement),
91
+ },
85
92
  messageId: 'component',
86
93
  node,
87
94
  });
@@ -1 +1 @@
1
- {"version":3,"file":"PreferComponent.js","sourceRoot":"","sources":["../../../src/oxlint/rules/PreferComponent.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PreferComponent.js","sourceRoot":"","sources":["../../../src/oxlint/rules/PreferComponent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /** Points plain flex and grid wrappers at `Stack`, `Inline`, and `Grid`. @module */
2
+ import type { Rule } from '@oxlint/plugins';
3
+ /**
4
+ * Reports a block element whose only styles lay out its children with flex or grid and a gap.
5
+ * A column maps to `Stack`, a row to `Inline`, and equal grid tracks to `Grid`. An element
6
+ * with a `className`, a spread that the rule cannot read, or any other declaration passes.
7
+ */
8
+ export declare const rule: Rule;
9
+ //# sourceMappingURL=PreferLayout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PreferLayout.d.ts","sourceRoot":"","sources":["../../../src/oxlint/rules/PreferLayout.ts"],"names":[],"mappings":"AAAA,oFAAoF;AACpF,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAoC3C;;;;GAIG;AACH,eAAO,MAAM,IAAI,EAAE,IAqDlB,CAAA"}
@@ -0,0 +1,90 @@
1
+ import * as Docs from '../internal/Docs.js';
2
+ import * as Styles from '../internal/Styles.js';
3
+ // Block elements that a layout component renders through `render`.
4
+ const tags = new Set([
5
+ 'article',
6
+ 'aside',
7
+ 'div',
8
+ 'footer',
9
+ 'form',
10
+ 'header',
11
+ 'main',
12
+ 'nav',
13
+ 'ol',
14
+ 'section',
15
+ 'ul',
16
+ ]);
17
+ // Declarations that the layout components set. Any other declaration makes the element more than a
18
+ // layout wrapper, so the rule skips it.
19
+ const layout = new Set([
20
+ 'alignItems',
21
+ 'columnGap',
22
+ 'display',
23
+ 'flexDirection',
24
+ 'flexWrap',
25
+ 'gap',
26
+ 'gridTemplateColumns',
27
+ 'justifyContent',
28
+ 'rowGap',
29
+ ]);
30
+ // Equal tracks that `columns` or `fit` on `Grid` produce.
31
+ const tracks = /^repeat\(\s*(?:[1-46]|12|auto-fill|auto-fit)\s*,/;
32
+ /**
33
+ * Reports a block element whose only styles lay out its children with flex or grid and a gap.
34
+ * A column maps to `Stack`, a row to `Inline`, and equal grid tracks to `Grid`. An element
35
+ * with a `className`, a spread that the rule cannot read, or any other declaration passes.
36
+ */
37
+ export const rule = {
38
+ meta: {
39
+ docs: {
40
+ description: 'Use `Stack`, `Inline`, or `Grid` instead of a plain flex or grid wrapper.',
41
+ },
42
+ messages: {
43
+ layout: "Use '{{component}}' from '@tempoxyz/ds' instead of laying out <{{element}}> with {{display}} and a gap. See {{url}}",
44
+ },
45
+ schema: [],
46
+ type: 'suggestion',
47
+ },
48
+ create(context) {
49
+ return Styles.visit((element) => {
50
+ if (!tags.has(element.tag) || element.open)
51
+ return;
52
+ const declarations = element.declarations;
53
+ if (![...declarations.keys()].every((property) => layout.has(property)))
54
+ return;
55
+ if (!['columnGap', 'gap', 'rowGap'].some((property) => declarations.has(property)))
56
+ return;
57
+ const display = Styles.text(declarations.get('display'));
58
+ const component = (() => {
59
+ if (display === 'flex' || display === 'inline-flex') {
60
+ const direction = declarations.has('flexDirection')
61
+ ? Styles.text(declarations.get('flexDirection'))
62
+ : 'row';
63
+ if (direction === 'column')
64
+ return 'Stack';
65
+ if (direction === 'row')
66
+ return 'Inline';
67
+ return undefined;
68
+ }
69
+ if (display !== 'grid' && display !== 'inline-grid')
70
+ return undefined;
71
+ if (!declarations.has('gridTemplateColumns'))
72
+ return 'Stack';
73
+ const columns = Styles.text(declarations.get('gridTemplateColumns'));
74
+ return columns !== undefined && tracks.test(columns) ? 'Grid' : undefined;
75
+ })();
76
+ if (component)
77
+ context.report({
78
+ data: {
79
+ component,
80
+ display: display?.replace('inline-', '') ?? '',
81
+ element: element.tag,
82
+ url: Docs.component(component),
83
+ },
84
+ messageId: 'layout',
85
+ node: element.node,
86
+ });
87
+ });
88
+ },
89
+ };
90
+ //# sourceMappingURL=PreferLayout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PreferLayout.js","sourceRoot":"","sources":["../../../src/oxlint/rules/PreferLayout.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /** Points hand-built bars at `Progress` and `ListGroup.Meter`. @module */
2
+ import type { Rule } from '@oxlint/plugins';
3
+ /**
4
+ * Reports an empty `div` or `span` whose inline `width` or `inlineSize` is a computed percentage,
5
+ * such as a template literal that ends in `%`, which draws the fill of a hand-built bar. An element
6
+ * with children passes, since a resizable pane sets its width the same way.
7
+ */
8
+ export declare const rule: Rule;
9
+ //# sourceMappingURL=PreferProgress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PreferProgress.d.ts","sourceRoot":"","sources":["../../../src/oxlint/rules/PreferProgress.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,OAAO,KAAK,EAAU,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAInD;;;;GAIG;AACH,eAAO,MAAM,IAAI,EAAE,IAsClB,CAAA"}
@@ -0,0 +1,43 @@
1
+ import * as Docs from '../internal/Docs.js';
2
+ import * as Styles from '../internal/Styles.js';
3
+ /**
4
+ * Reports an empty `div` or `span` whose inline `width` or `inlineSize` is a computed percentage,
5
+ * such as a template literal that ends in `%`, which draws the fill of a hand-built bar. An element
6
+ * with children passes, since a resizable pane sets its width the same way.
7
+ */
8
+ export const rule = {
9
+ meta: {
10
+ docs: { description: 'Use `Progress` or `ListGroup.Meter` instead of a hand-built bar.' },
11
+ messages: {
12
+ bar: "Use 'Progress' from '@tempoxyz/ds', or 'ListGroup.Meter' in a ListGroup row, instead of drawing a bar with <{{element}}> and a percentage width. See {{url}}",
13
+ },
14
+ schema: [],
15
+ type: 'suggestion',
16
+ },
17
+ create(context) {
18
+ function percentage(node) {
19
+ if (node?.type === 'TemplateLiteral')
20
+ return node.expressions.length > 0 && node.quasis.at(-1)?.value.cooked?.trim() === '%';
21
+ if (node?.type === 'BinaryExpression')
22
+ return node.operator === '+' && node.right.type === 'Literal' && node.right.value === '%';
23
+ return false;
24
+ }
25
+ return Styles.visit((element) => {
26
+ if (element.tag !== 'div' && element.tag !== 'span')
27
+ return;
28
+ const parent = element.node.parent;
29
+ const empty = parent.type === 'JSXElement' &&
30
+ parent.children.every((child) => child.type === 'JSXText' && child.value.trim() === '');
31
+ if (!empty)
32
+ return;
33
+ if (percentage(element.declarations.get('width')) ||
34
+ percentage(element.declarations.get('inlineSize')))
35
+ context.report({
36
+ data: { element: element.tag, url: Docs.component('Progress') },
37
+ messageId: 'bar',
38
+ node: element.node,
39
+ });
40
+ });
41
+ },
42
+ };
43
+ //# sourceMappingURL=PreferProgress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PreferProgress.js","sourceRoot":"","sources":["../../../src/oxlint/rules/PreferProgress.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,IAAI,MAAM,qBAAqB,CAAA;AAC3C,OAAO,KAAK,MAAM,MAAM,uBAAuB,CAAA;AAE/C;;;;GAIG;AACH,MAAM,CAAC,MAAM,IAAI,GAAS;IACxB,IAAI,EAAE;QACJ,IAAI,EAAE,EAAE,WAAW,EAAE,kEAAkE,EAAE;QACzF,QAAQ,EAAE;YACR,GAAG,EAAE,8JAA8J;SACpK;QACD,MAAM,EAAE,EAAE;QACV,IAAI,EAAE,YAAY;KACnB;IACD,MAAM,CAAC,OAAO;QACZ,SAAS,UAAU,CAAC,IAA6B;YAC/C,IAAI,IAAI,EAAE,IAAI,KAAK,iBAAiB;gBAClC,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,GAAG,CAAA;YACxF,IAAI,IAAI,EAAE,IAAI,KAAK,kBAAkB;gBACnC,OAAO,IAAI,CAAC,QAAQ,KAAK,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,KAAK,GAAG,CAAA;YAC3F,OAAO,KAAK,CAAA;QACd,CAAC;QAED,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,EAAE;YAC9B,IAAI,OAAO,CAAC,GAAG,KAAK,KAAK,IAAI,OAAO,CAAC,GAAG,KAAK,MAAM;gBAAE,OAAM;YAE3D,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAA;YAClC,MAAM,KAAK,GACT,MAAM,CAAC,IAAI,KAAK,YAAY;gBAC5B,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;YAEzF,IAAI,CAAC,KAAK;gBAAE,OAAM;YAClB,IACE,UAAU,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBAC7C,UAAU,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;gBAElD,OAAO,CAAC,MAAM,CAAC;oBACb,IAAI,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE;oBAC/D,SAAS,EAAE,KAAK;oBAChB,IAAI,EAAE,OAAO,CAAC,IAAI;iBACnB,CAAC,CAAA;QACN,CAAC,CAAC,CAAA;IACJ,CAAC;CACF,CAAA"}
@@ -0,0 +1,9 @@
1
+ /** Points native elements styled as cards at `Surface`. @module */
2
+ import type { Rule } from '@oxlint/plugins';
3
+ /**
4
+ * Reports an `article`, `aside`, `div`, `li`, or `section` whose styles draw a card: a corner
5
+ * radius and padding with a border or a background. A pill radius, such as `full`, and a
6
+ * positioned element, such as a hand-built popover, pass.
7
+ */
8
+ export declare const rule: Rule;
9
+ //# sourceMappingURL=PreferSurface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PreferSurface.d.ts","sourceRoot":"","sources":["../../../src/oxlint/rules/PreferSurface.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAU3C;;;;GAIG;AACH,eAAO,MAAM,IAAI,EAAE,IAqDlB,CAAA"}